I'm writing a web app in Ruby that I'd like to be able to unit-test.
The application is a webmail system that requires the client to
support cookies. Is there any recommended way of doing this?
In Rails, you can test your application at all three layers of the MVC.
The framework will even generate placeholder test suites where all you
need to do is put in the cases. The model testing is labelled unit
testing and the view/controller testing is labelled functional testing.
I gather that it's the functional testing you're interested in. With
Rails, this is done by passing a TestRequest to the controller instead
of the real CgiRequest. Once this TestRequest has been processed,
you'll have access to all the internals of the response. You can see
which objects where assigned either directly to the template or to the
session and which cookies were sent. And you can see whether the result
was just a redirect or a render.
Testing at the controller level appears to hold the best bang-for-buck
ratio in functional testing. While it's certainly also possible to test
the final XHTML (if you write proper XHTML, you can instantiate the
response body with REXML and use XPath for queries), it's a much more
brittle and time-consuming approach. And you'll have to test the view
anyway with a human eye to ensure that everything is alright.
Another advantage of testing at the controller layer is speed. When I
was using WebUnit on my PBook 1.33, each test case took just under a
second to run. There's an immense overhead in setting up WebUnit,
accessing the application through Apache, and then parsing the XHTML
for queries. Less than a second may not sound like a lot, but if you
have a test suite of 400 cases that's a run time of more than six
hours.
An example of functional testing at the controller layer in Rails:
def show
@person = Person.find(@params["id"])
end
def test_show
@request.path = "/addressbook/show/15"
@request.action = "show"
response = AddressbookController.process_test(@request)
assert_equal "200 OK", response.headers["status"]
assert_equal "addressbook/show", response.template.first_render
assert_equal Person.find(15), response.template.assigns["person"]
end
--
David Heinemeier Hansson,
http://www.rubyonrails.org/ -- Web-application framework for Ruby
http://www.instiki.org/ -- A No-Step-Three Wiki in Ruby
http://www.basecamphq.com/ -- Web-based Project Management
http://www.loudthinking.com/ -- Broadcasting Brain
http://www.nextangle.com/ -- Development & Consulting Services