Unit-testing a Web Application

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?

Is there a Ruby equivalent to Java's HttpUnit or some more
general-purpose library that can handle HTTP with cookies?

Thanks,
Bill

Bill Atkins wrote:

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?

I have an approach, acquired by stealing what seemed to be the best ideas floated here and elsewhere. YMMV, etc.

Generally, I try to push the presentation layer out as far as I can. Ideally, the core of the application should work just as well as a command-line program or a set of Web services. Therefore (or so goes the theory), by the time you get to testing the graphic interface, you're past testing whether code emits correct values when given assorted input. Now you want to see that the values are correctly populating some UI, and the UI is correctly triggering some events.

One way to do this is to write the app to exchange XML or some other form of presentational-neutral text. Unit tests for the application proper can then use regexen or whatever to verify the resulting strings.

Testing the actual Web browser part is harder, because of the differences among browsers. I've been using the CIEController lib [0] to drive Internet Explorer from Ruby. I am not aware of anything similar for Mozilla. But it helps verify some coarse-grained behavior.

I still end up having to do a fair amount of visual inspection and manual clicking with assorted browsers; not sure how to get around that part. But I try to put that off until I'm reasonably sure the server code is behaving correctly, independent of the browser.

James

[0] http://www.clabs.org/wtr/index.cgi?page=/AboutWtr

Hello,

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?

Is there a Ruby equivalent to Java's HttpUnit or some more
general-purpose library that can handle HTTP with cookies?

There is a library called WebUnit:

   http://www.xpenguin.biz/download/webunit/index-en.html

I also work on a library which may be of interest:

   http://www.narf-lib.org

I'm would go so far as to recommend what the right solution is. Narf may reflect a bit strongly what I would like when testing web applications.

Cheers,

Patrick

···

On Sunday, August 8, 2004, at 01:36 PM, Bill Atkins wrote:

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