Simpler Test-driven Web Development with Sinatra and MongoDB
The potent combination of an extremely flexible and forgiving (migration-free!) database like MongoDB and an extremely lightweight web app framework like Sinatra allows you to do test-driven development much more simply than with Ruby on Rails / MySQL or lightweight web frameworks in other languages.
We will be using Rack::Test for more "acceptance"-style testing and Test::Unit for traditional unit testing, which will be very comfortable for programmers already familiar with XUnit-style testing. Come create a complete, working web app in record time test-first using Sinatra and MongoDB.
Topics covered:
- Ruby
- Sinatra
- MongoDB
- Mongo_Mapper
- Test::Unit
- Rack::Test
- Markup Validity
Preparation: Any laptop with Ruby (ideally 1.9+) installed will do...
- gem install sinatra
- gem install mongo_mapper
- gem install rack-test
- gem install markup_validity
download the appropriate MongoDB binary
- extract MongoDB package somewhere convenient
- create a /data/db directory on the same drive/mount where you extracted it
As a teaser, here's an illustration of our simple first test
1 # hello_test.rb
2
3 require 'rubygems'
4 require 'rack/test'
5 require 'test/unit'
6 require 'hello' # <-This specifies the SUT
7
8 class MyAppTest < Test::Unit::TestCase
9 include Rack::Test::Methods
10
11 def app
12 Sinatra::Application
13 end
14
15 def test_my_default
16 get '/'
17 assert_equal 'Hello World!', last_response.body
18 end
19 end
And the second, which causes a slight refactor of the first test
1 require 'markup_validity'
2 .
3 .
4 .
5 def test_my_default
6 get '/'
7 assert(last_response.body.include?('Hello World!'), "No 'Hello World!' in '#{last_response.body}'")
8 end
9
10 def test_body_is_html
11 get '/'
12 assert_xhtml_transitional(last_response.body)
13 end
14 .
15 .
16 .
Eventually, we'll be asserting against the HTML output, like:
1 require 'nokogiri'
2 .
3 .
4 .
5 def test_input_field_named_greetee
6 get '/'
7 doc = Nokogiri::HTML(last_response.body)
8 assert_equal('greetee', doc.xpath('//form/input/@name'))
9 end
10 .
11 .
12 .
The "Requirements" of the project are:
- Web application
- Use a database (shared with other apps)
- Enter 1 person at a time to greet
- Greetings page greets all people in database
Consistent HTML look for all pages, use image.
