Sinatra tests always 404'ing - ruby

I have a very simple Sinatra app which I'm having trouble testing.
Basically, every single request test returns a 404 when I know from testing in the browser that the request works fine. Any ideas as to what the problem might be?
test_helper.rb:
ENV["RACK_ENV"] = 'test'
$: << File.expand_path(File.dirname(__FILE__) + '/../lib')
require 'app'
Sinatra::Synchrony.patch_tests!
class Test::Unit::TestCase
include Rack::Test::Methods
end
app_test.rb
require 'test_helper'
class AppTest < Test::Unit::TestCase
def app
#app ||= Sinatra::Application
end
def test_it_says_hello
get "/"
assert_equal 200, last_response.status
end
end
app.rb
$: << 'config'
require "rubygems" require "bundler"
ENV["RACK_ENV"] ||= "development"
Bundler.require(:default, ENV["RACK_ENV"].to_sym)
require ENV["RACK_ENV"]
class App < Sinatra::Base register Sinatra::Synchrony
get '/' do
status 200
'hello, I\'m bat shit crazy and ready to rock'
end
end
Gemfile
source :rubygems
gem 'daemons'
gem 'sinatra'
gem 'sinatra-synchrony', :require => 'sinatra/synchrony'
gem 'resque'
gem 'thin'
group :test do
gem 'rack-test', :require => "rack/test"
gem 'test-unit', :require => "test/unit"
end
Why can I not get this normally very simple thing working?

I had quite the same problem with only HTTP-404 coming in return.
I solved it with giving another return in the "app" function.
class IndexClassTest < Test::Unit::TestCase
def app
#app = Foxydeal #appname NOT Sinatra::Application
end
...
Also
Sinatra::Synchrony.patch_tests!
seems to be obsolete.

Under your app_test.rb do this instead of what you have now:
def app
#app ||= App.new
end
This will work with your your class style like you had it in the beginning, no need to switch to the non-class/modular style.

It may seem logical, but are your routes configured correctly? If a route isn't correctly configured, it'll throw 404 errors left and right.

Figured it out.
app.rb
$: << 'config'
require "rubygems" require "bundler"
ENV["RACK_ENV"] ||= "development" Bundler.require(:default,
ENV["RACK_ENV"].to_sym) require ENV["RACK_ENV"]
class App < Sinatra::Base
register Sinatra::Synchrony
end
get '/' do
status 200
'hello, I\'m bat shit crazy and ready to rock'
end

You may simply do this:
class AppTest < Test::Unit::TestCase
def app
Sinatra::Application
end
You can get a solid understanding of sinatra tests by reading Learning From the Masters: Sinatra Internals and Rack::Test

Related

Reloading models and helpers with Sinatra::Reloader

I'm trying to automatically reload a Sinatra project in JRuby on Windows Vista/7. I'm using Sinatra::Reloader from Sinatra-contrib. Unfortunately, it only seems to work for controllers. Any changes to models and helpers aren't reloaded.
Am I using also_reload incorrectly or something?
Here's what my project looks like:
/app.rb
require 'sinatra'
require 'sinatra/reloader'
require 'json'
class App < Sinatra::Application
enable :sessions
enable :logging
register Sinatra::Reloader
also_reload "models/*.rb"
also_reload "helpers/*.rb"
helpers do
include Rack::Utils
alias_method :h, :escape_html
end
end
require_relative 'helpers/init'
require_relative 'models/init'
require_relative 'controllers/init'
/controllers/init.rb
enable :sessions
require_relative 'auth'
require_relative 'customer'
require_relative 'policy'
require_relative 'forms'
/helpers/init.rb
require_relative 'auth_helper'
require_relative 'customer_helper'
require_relative 'flash_helper'
require_relative 'form_helper'
require_relative 'policy_helper'
/models/init.rb
require 'lib/sqljdbc4.jar'
require 'sequel'
require 'logger'
Java::com.microsoft.sqlserver.jdbc.SQLServerDriver
url = 'foo'
DB = Sequel.connect(url)
DB.loggers << Logger.new($stdout)
Sequel.inflections do |inflect|
inflect.clear :all
end
files = [
:customer,
:customer_email,
:phone_number ]
files.each do |f|
require_relative f.to_s
end
Under current implementation of yours, let's say you change something in helpers/auth_helper.rb. This file gets reloaded but since the helpers/init.rb is unchanged, it won't be reloaded by sinatra-reloader and you won't see the changes. Have you tried shotgun gem?

Sinatra + Rspec2 - Use Sessions/Helpers?

I am trying to test my Sinatra app using Rspec2 but I can't get access to sessions or helper methods in my tests.
spec_helper:
require File.dirname(__FILE__) + "/../myapp.rb"
require 'rubygems'
require 'sinatra'
require 'rack/test'
require 'rspec'
require 'factory_girl'
set :environment, :test
RSpec.configure do |conf|
conf.include Rack::Test::Methods
end
def app
Sinatra::Application
end
app_spec.rb:
require File.dirname(__FILE__) + "/../spec_helper.rb"
describe 'Something' do
it "should do something" do
session["aa"] = "Test"
end
end
This throws an error, can't find session variables. Similarly I can't use helper methods which are defined in my app.
I run my tests using rspec specs/app_spec/app_spec.rb.
What am I doing wrong?
Assuming you've got your specs and spec helper in the /spec dir, then this line should go at the top of your spec:
require_relative "./spec_helper.rb"
I also like to use File.expand_path and File.join as it's more reliable than doing it yourself, e.g.
require File.dirname(__FILE__) + "/../spec_helper.rb"
becomes
require_relative File.expand_path( File.join File.dirname(__FILE__), "/../spec_helper.rb" )
Also, I don't tend to require "sinatra", the app has that. If you're missing bits from sinatra then maybe, but I add things like this instead through rack:
ENV['RACK_ENV'] = 'test'
Finally, if your Sinatra app is using the modular style then you'll have to include it too. I do this at the top of a spec, for example:
describe "The site" do
include Rack::Test::Methods
include MyApp
let(:app) { MyApp.app }
YMMV. Let us know if any of this works.
A different test to try:
before(:all) { get "/" }
subject { last_response }
it { should be_ok }

problem with task rake, ruby

I have got a task in rake that run my server sinatra , it doesn't work , the same script in ruby works. Why ?? can I run server sinatra in rake task??
task :server do
begin
require 'rubygems'
require 'sinatra'
rescue LoadError
p "first install sinatra using:"
p "gem install sinatra"
exit 1
end
get '/:file_name' do |file_name|
File.read(File.join('public', file_name))
end
exit 0
end
Create a class that is inherited from a Sinatra::Base class
#app.rb
require 'sinatra'
class TestApp < Sinatra::Base
get '/' do
"Test"
end
end
And then run your application from rake:
#Rakefile
$:.unshift File.join(File.dirname(__FILE__), ".")
require 'rake'
require 'app'
task :server do
TestApp.run!
end

How mix in routes in Sinatra for a better structure

I found nothing about how I can mix-in routes from another module, like this:
module otherRoutes
get "/route1" do
end
end
class Server < Sinatra::Base
include otherRoutes
get "/" do
#do something
end
end
Is that possible?
You don't do include with Sinatra. You use extensions together with register.
I.e. build your module in a separate file:
require 'sinatra/base'
module Sinatra
module OtherRoutes
def self.registered(app)
app.get "/route1" do
...
end
end
end
register OtherRoutes # for non modular apps, just include this file and it will register
end
And then register:
class Server < Sinatra::Base
register Sinatra::OtherRoutes
...
end
It's not really clear from the docs that this is the way to go for non-basic Sinatra apps. Hope it helps others.
You could do this:
module OtherRoutes
def self.included( app )
app.get "/route1" do
...
end
end
end
class Server < Sinatra::Base
include OtherRoutes
...
end
Unlike Ramaze, Sinatra's routes are not methods, and so cannot use Ruby's method lookup chaining directly. Note that with this you can't later monkey-patch OtherRoutes and have the changes reflected in Server; this is just a one-time convenience for defining the routes.
I prefer the use of sinatra-contrib gem to extend sinatra for cleaner syntax and shared namespace
# Gemfile
gem 'sinatra', '~> 1.4.7'
gem 'sinatra-contrib', '~> 1.4.6', require: 'sinatra/extension'
# other_routes.rb
module Foo
module OtherRoutes
extend Sinatra::Extension
get '/some-other-route' do
'some other route'
end
end
end
# app.rb
module Foo
class BaseRoutes < Sinatra::Base
get '/' do
'base route'
end
register OtherRoutes
end
end
sinata-contrib is maintained alongside the sinatra project
Well you can also use the map method to map routes to your sinatra apps
map "/" do
run Rack::Directory.new("./public")
end
map '/posts' do
run PostsApp.new
end
map '/comments' do
run CommentsApp.new
end
map '/users' do
run UserssApp.new
end
Just my two cents:
my_app.rb:
require 'sinatra/base'
class MyApp < Sinatra::Base
set :root, File.expand_path('../', __FILE__)
set :app_file, __FILE__
disable :run
files_to_require = [
"#{root}/app/helpers/**/*.{rb}",
"#{root}/app/routes/**/*.{rb}"
]
files_to_require.each {|path| Dir.glob(path, &method(:require))}
helpers App::Helpers
end
app/routes/health.rb:
MyApp.configure do |c|
c.before do
content_type "application/json"
end
c.get "/health" do
{ Ruby: "#{RUBY_VERSION}",
Rack: "#{Rack::VERSION}",
Sinatra: "#{Sinatra::VERSION}"
}.to_json
end
end
app/helpers/application.rb:
module App
module Helpers
def t(*args)
::I18n::t(*args)
end
def h(text)
Rack::Utils.escape_html(text)
end
end
end
config.ru:
require './my_app.rb'

Webrat Mechanize outside of Rails

I'm trying to use Webrat in a standalone script to automate some web browsing. How do I get the assert_contain method to work?
require 'rubygems'
require 'webrat'
include Webrat::Methods
include Webrat::Matchers
Webrat.configure do |config|
config.mode = :mechanize
end
visit 'http://gmail.com'
assert_contain 'Welcome to Gmail'
I get this error
/usr/lib/ruby/gems/1.8/gems/webrat-0.6.0/lib/webrat/core/matchers/have_content.rb:57:in 'assert_contain': undefined method assert' for #<Object:0xb7e01958> (NoMethodError)
assert_contain and other assertions are methods of test/unit, try to require it and use webrat from inside a test method:
require 'test/unit'
class TC_MyTest < Test::Unit::TestCase
def test_fail
assert(false, 'Assertion was false.')
end
end
anyway i haven't tested it but I have a working spec_helper for rspec if this can interest you:
require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_ROOT)
require 'spec/rails'
require "webrat"
Webrat.configure do |config|
config.mode = :rails
end
module Spec::Rails::Example
class IntegrationExampleGroup < ActionController::IntegrationTest
def initialize(defined_description, options={}, &implementation)
defined_description.instance_eval do
def to_s
self
end
end
super(defined_description)
end
Spec::Example::ExampleGroupFactory.register(:integration, self)
end
end
plus a spec:
# remember to require the spec helper
describe "Your Context" do
it "should GET /url" do
visit "/url"
body.should =~ /some text/
end
end
give it a try I found it very useful (more than cucumber and the other vegetables around) when there is no need to Text specs (features) instead of Code specs, that I like the most.
ps you need the rspec gem and it installs the 'spec' command to execute your specs.

Resources