Functional Test Driven Development with Grails and WebTest (Lee Butts)
Grails, Lee Butts, Testing July 24th, 2008
Lee Butts has written a good post on applying functional testing to Grails apps using Canoo WebTest and the WebTest plugin. This is not an introduction to the WebTest plugin nor an article on why functional testing matters, the advantages of both may be clear to many by now, so Lee concentrates in two issues that gave him some trouble, at least on how he wanted the tests to be run. These are
- the speed of execution of a set of tests
- how to specify a subset of test to be run (a custom TestSuite if you will)
The Grails WebTest plugin comes with a script which will start your application, run all your test, and shut down the application. This is great for checking your code before checking in or for running on your continuous integration server. However, if you would like to use a WebTest to drive out some functionality it is far too slow.
To get around this I have been using a custom script and parent class for my WebTests. The script is basically a copy of RunWebtest.groovy supplied by plugin with the start/stop application code removed. It also has a small section of code to parse a class patttern and method pattern as arguments. It needs to be placed in the plugins/webtest-0.5/scripts directory of your application so that it can access the required WebTest configuration and resources.
This allows for a command such as:
grails run-webtest-only MyDomain edit
which will run all test methods containing the word edit but only those methods found in classes with a name containing the word MyDomain.
That is half of the solution, as it let you specify a subset of tests. One thing to notice is that because the database state is not refreshed between tests it forces you to code in a ’stateless’ manner, some may object on this as functional testing (or integration testing) relies on several components working together, where a predefined state must be set before the actual test. The other half of the solution is to plug in a custom TestSuite so that the subset of tests can be run.
The second part of the solution is the custom parent class for the WebTests. By default, the WebTest plugin requires you to add a suite method to your WebTest to specify the order in which to run the test cases contained within it. This is very useful if there are dependencies between the cases and testA must run before testB for example. To me, this is a bit of a smell that your tests are too fragile. If testA must run before testB in order to set up some state, refactor the code that creates that state into a method and re-use it in testB with unique values so that you can run testB regardless of database state.
Of course there are always exceptions, especially when it comes to keeping test execution time to a minimum, and in reality it may be better to set up common data once and re-use it in several tests. My opinion above is given with a “in an ideal world” disclaimer.
Apologies, I’m getting side tracked! What my custom parent class does is model JUnit in that it automatically builds a suite from all methods beginning in ‘test’. It also applies the class and method filters you gave to the run-webtest-only script which are passed through from Gant via system properties.
Now with the help of the WebTestRecorder firefox plugin I can start to drive out a new page, menu item or behaviour.
Finally, following the spirit of TDD, Lee demonstrates a typical scenario for adding new functionality on a particular app. Starting with the WebTestRecorder firefox plugin, he launches a web session recording every single step of the new scenario, tweaking the test code when it makes sense and finally running the failing test (remember a good test starts red), then he simply writes enough code to make the test pass.
About
[…] Blogosphère http://mguillem.wordpress.com/2007/10/29/webtest-vs-selenium-webtest-wins-13-5/ http://www.deveshwar.com/softengg/test/CanooWebtestBestPractices http://www.groovyongrails.com/article/107 […]