Archive for June, 2008

Watir – first impressions

June 24, 2008

Our product doesn’t have unit tests. There, I said it. For a long time I’ve been looking for a way to build unit tests. There are three factors that prevented me to do so until now:

  1. It seems not to be really needed. When testing is needed, developers go over an installation and check that everything is working. Building a suite of tests to test all possible scenarios seems to be a huge task that doesn’t worth the effort.
  2. This is a web application that is constantly changing, so it seems hard to write robust test that will not break on every change. In addition, it uses a session ID that is passed in the URL, so URLs are different on every run.
  3. The data keeps changing. Our data is on the mainframe, and it is owned and used by other teams so we can’t expect to have the same data all the time, which makes it problematic to build solid tests.

In the past I tried using Selenium, but never really fell in love with it, and never got the time to deeply look into it and test it.
Recently I saw Ofer’s post about Watir and decided to take a better look at it and see if we can use it. Since I’m fluent at Javascript, and had a recent experience with Perl working on an installation automation project for a few months, catching Ruby was quite easy. As Ofer observed, Ruby seems to be a really nice language, but I have some problems adapting to Watir. For example, it took me sometime to understand how Javascript code can be invoked from Watir, but now I know it is done using:

$browser.ie.Document.parentWindow.execScript(js_expression)

At first, since I come from normal OO languages, I thought of creating a base ProductUnitTest class that derives from Watir::TestCase, and then, for each version or fix pack, we will create a VersionXXUnitTest class that will derive from ProductUnitTest. However, this doesn’t work well, since Test::Unit looks for all the included classes that derived from Test::Unit::TestCase, and since we would have to require ProductUnitTest in order to derived from it, Test::Unit will see two such class and will run the tests in ProductUnitTest twice – once for ProductUnitTest, and once for the derived VersionXXUnitTest.

Checking further, I came to the idea I have to use Ruby’s mixins, which is somewhat similar to Java’s interfaces, but more comfortable and easy to use, since Ruby is a dynamic language. So now, I define all basic tests and helper methods (like setup and teardown – see next post for more details on this) in a module named ProductUnitTest, and then, for each version, I define a VersionXXUnitTest class that derive from Watir::TestCase, and then includes ProductUnitTest so all the tests (and helper methods) are there, but only invoked once, for VersionXXUnitTest.

To conclude, Watir seems like a very nice framework to test our web application, and this will probably solve problem #2 above. I plan to broaden its use when we start building our next fix pack, where we have specific things we need to fix, and whenever we fix something, we should write a unit test for it right away. This is easier then writing and maintaining unit tests for an entirely new version that keeps changing. I hope that once our developers get used to it and see how it can help integration and acceptance tests they will see its value and overcome problem #1 above. I still need to find a good way to bypass problem #3.

I already showed what I did to Amit from QA, and she really liked it and said it might be useful for them as well.

P.S.
Another nice benefit of learning Ruby is that now I better understand some of the design made by the Prototype team members, which were clearly thinking in Ruby, as they are using Ruby on Rails.