I've written in an earlier blog entry about writing acceptance tests in Java for a Flex front ended web app, using Selenium RC. Here I'll describe how we added those tests to our continuous integration build, using a Hudson job as part of our build-and-deploy pipeline.
Our web app comprises two components, a Java server-side component and a Flex client-side component. The Java component is built by a Hudson job as a war file. The Flex component is built by another Hudson job as a zip file. These two Hudson jobs are independent, fairly standard projects built by Ant, each with its own set of unit tests. To run acceptance tests, we need both components to be deployed into the target environment. We created a third Hudson job which aims to deploy the latest artifacts from the Java and Flex jobs, start up Tomcat and Selenium, run the acceptance test suite, and shut down Tomcat and Selenium. This Hudson job depends on the other two jobs and its build is activated when either of those two completes.
As we are already using Ant to control the two component builds, and our acceptance tests are written in Java, we decided to use the Ant build for the Java component as the home for the acceptance test build. Here's the target to run the acceptance tests in the Hudson CI environment:
The task depends on targets to compile the acceptance tests, create the test database schema, load reference data, download and deploy the CI builds of the Java and Flex artifacts, start up Selenium RC, and finally run the acceptance test suite. Here's the deploy-ci task:
The run-acc-tests task runs the acceptance test suite of Selenium/JUnit tests against the deployed artifacts and finishes by shutting down tomcat and Selenium-RC.
There were one or two wrinkles which we had to iron out before our Hudson dashboard showed a happy sun.
- Selenium needs a display, but Hudson is running on a headless server.
- Other builds or processes run Selenium servers; there was port contention.
- Similarly, other builds or processes run Tomcat; there was port contention.
- Acceptance tests ran but failed with diagnostics like "window.document.MyFlexApp has no properties".
Solutions we used were:
- We configured the Hudson job with "Run Xvnc during build".
- We chose a port for the Selenium server that doesn't clash with any other server. We did this in the ant task that starts Selenium:
- Similarly, we chose a non-clashing port for Tomcat.
- We realized that our app has a Flex front-end but the browser installed on the Hudson box and used for the Selenium tests did not have a Flash plug-in installed. So the Flex application object was never initialized. Once we'd installed the plug-in, the acceptance tests started passing. Doh!