Main

February 16, 2009

HippoCMS 7 integration testing with Selenium

Integration tests are designed to check the functionality of an application as a whole, rather than focussing on the internal workings of individual software modules, which is the domain of normal unit testing.

Selenium
Selenium is such a toolkit to create and run automated integration tests. In our latest sprint (M11) we've used it to implemented a few simple test-cases.

* log in and out with different users
* perform some simple document editing
* create a new user and check if it is able to login

Creating new tests
New tests can be created using the Selenium IDE plugin (Firefox only); simply open HippoCMS 7 in Firefox, start test-recording in Selenium IDE and follow your test-script. These tests can than be replayed during integration-testing using the Selenium Remote Control, which takes care of creating a new Firefox instance, running the tests and shutting Firefox down again.

Stable markup ids
For Selenium to identify which DOM-element should be clicked or which text-field should be edited, it depends heavily on the id attribute of DOM-elements. This makes the presence of stable markup ids a must, meaning that a test should always be run with the same HTML as when it was recorded, or else it will fail for the wrong reasons.

Wicket however, and therefore HippoCMS 7, generates markup ids on the fly for Wicket components meaning they will differ from request to request, making them unsuitable for identifying a component in the browser DOM. To work around this problem Berry van Halderen wrote a patch that modifies the Wicket core in order to make it generate stable markup ids.

Handling Ajax requests
As a first attempt of handling Ajax requests, we've implemented a rather blunt approach: after sending an Ajax request, test for n seconds if a condition is met, like isTextPresent('Welcome to Hippo CMS'), else fail. In next sprints this will change by integrating Selenium with Wicket-Ajax and making it possible for WicketAjax to notify Selenium when a request has been handled.

Running the tests
We currently run our tests using the Apache Geronimo selenium-maven-plugin which deploys the quickstart-ear into Glassfish, starts Selenium, runs the tests, stop Selenium and undeploys the ear.

To get a better feeling of how this works out you can check out this video Arje Cahn made:

Use case testing with Selenium from Arje Cahn on Vimeo.

More info
If you like to run the tests on your local machine or create some yourself, be sure to read more on the documentation page once it is online.

April 18, 2006

Back to Basic, or flowscript actually

Doing (complex) eventcached DASL queries without the HippoJX generator can be a tedious task.
Clearly, the Cocoon Jxtemplate generator is a nice mechanism for a) passing sitemap parameters into the query and/or b) changing the semantics of the query based on the paramters values, but since it doesn't handle caching natively, the programmer has to use flowscript to create a custom cache-key from sitemap parameters and pass it into the Jxtemplate, together with a NOPValidity object. This means 2 matchers for every DASL (since most DASL's require custom parameters) and a lot of extra work == bad!

So we created the HippoJX generator which produces cache-keys automatically from the sitemap parameters passed to it, and always uses a SourceValidity. We can even specify what parameters should/shouldn't be used in the cache-key!

I've been updating an existing website still using the old flowscript->dasl scheme, to the new HippoJx solution, and found it very usefull and easy to set up.
Untill.. I had to use a java.util.StringTokenizer inside my JXtemplate.

(from cocoon-dev discussion 'Java objects in JX templates')

packages, classes, constructors, static methods, constants is available in jxtg via rhino ... Unfortunatelly in 2.1.x those variables are only properly initialized when flowscript is the controller. 2.2 artificialy creates those variables no matter if you already have rhino context available or not.

One more thing: this construct ${java.util.StringTokenizer(items, delims)} will work only when .jx is invoked from flow. This is due to the fact that neither JEXL nor JXPath is able to reference packages/create java
objects. The functionality in fact is provided by Rhino library.This is already fixed for 2.2-dev (still the dependency on Rhino remains).


So I gues I'm back to wrapping (some) of my DASL call's with flowscript again, untill 2.2 is released..