Simplified TDD with Sinatra autotest
Apr 17, 2010
General overview of what we’re building;
- Simple autotest compatible directory structure.
- Sinatra application.
- Sinatra unit test.
File setup:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
export project=MyApp
mkdir -p $project/{lib,test}
cd $project
cat <<EOT > test/test_app.rb
$:.unshift File.join(File.dirname(__FILE__),'..','lib')
require 'app'
require 'test/unit'
class AppTest < Test::Unit::TestCase
def test_fail
flunk 'Write your App tests!'
end
end
EOT
autotest
This should output something akin to the following, if you don’t get that then somethings amiss that you’ll need to investigate further.
1
2
3
4
5
6
7
8
/Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- app (LoadError)
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
from ./test/test_app.rb:4
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require'
from -e:2
from -e:2:in `each'
from -e:2
Next create a new file named ‘lib/app.rb’.
touch lib/app.rb
Once saved your test should kick to life with one failure:
1
2
3
1) Failure:
test_fail(AppTest) [./test/test_app.rb:8]:
Write your App tests!.
Hugely simplified test suite, but it gets you going and doesn’t contain reams of mystical cruft to debug.
Next up is introducing rack’s test suite, modify your test_app.rb to look like the following;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$:.unshift File.join(File.dirname(__FILE__),'..','lib')
require 'app'
require 'test/unit'
require 'rack/test'
set :environment, :test
class AppTest < Test::Unit::TestCase
include Rack::Test::Methods
def app
App
end
def test_fail
flunk 'Write your App tests!'
end
end
Back to a test that doesn’t run? Good!
Let’s get it back to a running test with the following change to ‘lib/app.rb’:
1
%w{rubygems sinatra}.each {|l| require l }
Now you should have a failing test. Lets start on something meaningful remove the test_fail method and add the following:
1
2
3
4
def test_root_is_accessible
get '/'
assert last_response.ok?
end
Your autotest should switch to the error output below:
1
2
3
4
1) Error:
test_root_is_accessible(AppTest):
NameError: uninitialized constant AppTest::App
./test/test_app.rb:13:in `app'
That’s an indicator we’re missing our application class. Dealing with one problem at a time lets implement the skeleton class in ‘lib/app.rb’ as outlined below.
1
2
class App < Sinatra::Base
end
You should get a failing test case with the output below, which indicates the route is not found.
1
2
3
1) Failure:
test_root_is_accessible(AppTest) [./test/test_app.rb:18]:
<false> is not true.
Next up lets add the route in ‘lib/app.rb’.
1
2
get '/' do
end
And there we go our first of hopefully many tests is now passing, congratulations!
For the source see;
<git://github.com/nfisher/Sinatra-Skeleton.git>