Skip to content

Testing WebFlow (Wonderful Webflow, Part II)

This posting follows on from Wonderful WebFlow. Probably best to take a look at that one first…

The post cited above developed a simple app. based around WebFlow, so now comes the time to test that app.

To loosely paraphrase Ford Prefect: Testing is important. Testing Dynamic Languages doubly so.

Grails understands the importance of testing and provides integrated facilities for unit and integration testing. Since WebFlow is integrated into Grails’ controllers there exists a specialised integration testing facility for WebFlow. This is a little bit ‘grungy’ (IMHO) but is straightforward and easy to use. The Grails integration test (which, according to the Grails convention, must be stored in the grails-app hierarchy in the directory test/integration) is:

public class CalcFlowTests extends grails.test.WebFlowTestCase {
   def getFlow() { new CalcController().calcFlow }

   void testShoppingCartFlow(){
      def viewSelection = startFlow()

      assertEquals "operand1", viewSelection.viewName

     flow.params.value = '10'
     viewSelection = signalEvent('next')
     assertEquals "operand2", viewSelection.viewName

     flow.params.value = '100'
     viewSelection = signalEvent('next')
     assertEquals "operator", viewSelection.viewName

     flow.params.operator = '+'
     viewSelection = signalEvent('next')
     assertEquals "results", viewSelection.viewName

     assertEquals 110, viewSelection.model.res
   }
}

This test is simple: it drives the flow through its various states, supplying the requisite parameters (it is this mechanism that seems ‘grungy’ to me) and performing a number of tests to confirm that the flow is operating as specified.

To execute the test, simply:

grails test-app

The test produces a number of XML reports that (via the magic that is XSLT) are transformed into HTML and plain text for the benefit of us poor humans.

Simple testing for a quite complex application. True Grails-y goodness, JUnit-style!

But wait! There’s more!

Not content with this simple, essentially low-level isolated testing, Grails also has a Canoo WebTest plugin that brings a lot more to the table. Let’s take a look.

WebTest is essentially a UI-less script-driven browser that is capable of evaluating its operation and the content it retrieves from the application against a series of assertions and requirements. Unlike the flow testing we have just seen this is higher-level and operates under the same conditions as a normal browser: it is subject to the vagaries of grottily-generated HTML, wierd JavaScript tricks, CSS ‘goodness’, the lot.

Even so, WebTest is powerful, easy to use and makes good reports. What more can one want?

As always with Grails, installing and configuring the plugin is simple:

grails install-plugin webtest
grails create-webtest Calc

This creates the files webtest/tests{TestSuite,CalcTest}.groovy (with a few others that are not immediately relevant to the task at hand).

CalcTest.groovy is generated according to the normal conventions for a Grails controller and normally would need very little hacking. Here however we have a WebFlow-based controller so a more radical makeover

is called for, leaving CalcTest.groovy looking like this:

class CalcTest extends grails.util.WebTest {

  // Unlike unit tests, functional tests are often sequence dependent.
  // Specify that sequence here.
  void suite() {
    testCalcFlow()
    // add tests for more operations here
  }

  def testCalcFlow() {
    webtest('Basic Calc flow; 1 + 1 = 2') {

      invoke '/calc', description: 'Move to Operand 1 Page'

      group(description: 'Operand 1 Page') {
        verifyTitle 'Get Operand 1'

        setInputField name: 'value', value: '1'
      }
      clickButton 'Next', description: 'Move to Operand 2 Page'

      group(description: 'Operand 2 Page') {
        verifyTitle 'Get Operand 2'
        setInputField name: 'value', value: '1'
      }
      clickButton 'Next', description: 'Move to Operator Page'

      group(description: 'Operator Page') {
        verifyTitle text: 'Get.*Operator', regex: true

        setSelectField name: 'operator', optionIndex: 0
      }
      clickButton 'Next'

      group(description: 'Results Page') {
        verifyTitle 'Results'
        verifyText '1 + 1 = 2'
      }
    }
  }
}

There’s really Nothing To See Here that we haven’t already seen (barring the ‘group’ concept, but that will become clear in the fullness of time), so let’s move right along.

The WebTest plugin makes testing easy:

grails run-webtest

This starts up the application “in the background” and then throws up a simple “please wait” dialog as the tests progress:

Once the tests are complete, WebTest creates some very comprehensive HTML reports in the directory webtest/reports:

It is nice to see the Green Bar reappear on these reports :-) It’s also nice to see the human-readable descriptive text extracted from the various steps into the report.

You may be thinking that making a lot of tests using even the simpler Groovy syntax would get tedious after a while. You’d be correct, but this is where WebTest’s WebTest Recorder comes in. This is a Mozilla Firefox plugin that does just what it’s name suggests it should do:

It doesn’t make a beautifully formatted, grouped script for you, but it does give a nice starting point (and may cut down on errors that could be introduced if the test were to be made ‘from scratch’).

I feel obliged to echo the warning that hits you as soon as you attempt to download the plugin:

WebTest is a good tool to demo: one can usually get a “wow!” or two from interested observers.

These reports are of sufficient quality that, in times of dire need, they can be placed under the nose of an interested PHB.

The use of ‘group’ in the test should now be clear. In the words of the WebTest manual: “…allows grouping and giving a description to a sequence of nested steps.” Groups make the reports easier to understand and give structure to the test itself.

One can drill-through the various reports and even view the actual pages retrieved by WebTest during a test run; this cache of pages proves very useful when the world didn’t go as expected!

So: this post has looked at two of the facilities Grails provides for testing a WebFlow for correct behaviour. It’s important to note that these facilities are available to any app., not just those making use of the WebFlow facility.

Up next: the thorny issue of Load testing.

Tags:

Java Enterprise Edition, JEE, JavaServer Pages, JSP, Tag Libraries, Servlets, Enterprise Java Beans, EJB, Java Messaging Service JMS, BEA Weblogic, JBoss, Application Servers, Spring Framework, Groovy, Grails, Griffon, Seam, Open Source, Service Oriented Architectures, SOA, Java 2 Standard Edition, J2SE