My current task is to support our teams in automatically testing a web application based on Ext JS. There is one team developing the main application while others develop plugins to this web application – with just the same requirement: Have a well tested deliverable after each two-weeks-sprint.
The problem: Have a maintainable and reusable test base for running the tests.
The solution: Provide Test-Wrappers for Ext JS components such as Buttons or Panels.
Ext JS is perfect for building Rich Internet Applications (short: RIA) such as an Editor for CMS contents. Based on JavaScript it provides a component structure with an object hierarchy. So a button and a panel are both childs of a base component which can be visible, hidden, enabled or disabled. But a panel is a container which can contain buttons and other components where a button again can be clicked.
What is more obvious than to provide a test base which relies on this object hierarchy? So have a TestButton class as wrapper to access the Ext JS button, click it, verify its label and so on.
Our test base, we call it test harness as you put it over the web application, is based on Java using Selenium WebDriver as direct access to the UI layer. If you have a well designed test harness, testers will not even need to know about WebDriver.
It is only the test harness, which knows how to access for example components through the Ext JS Component-Manager. It is only the test harness which has to deal with asynchronous checks to the UI. The complexity is well hidden from the testers which makes writing tests much easier – and they are easier to read.
Another advantage of such a test harness despite clean test code is the maintainability of the tests. In 2008 I described this in Testing Experience in the article Boon and Bane of GUI Test Automation (see 04/2008 or my article at QFS):
“Test execution script and GUI Maps can be maintained separately. As a consequence: If only the layout changes, you only have to adapt the GUI Map at one specific location.”
In contrast to the test harness the GUI Maps where just a database to look up how to access UI elements. In web context it could be a set of XPaths which can be access with a key from the tests.
The test harness allows much more, which I described as framework:
“To get around duplicated code, I decided to build up a framework. The goal was to create a framework to get as fast as possible to the test case you want to execute. If you need some kind of document to write to, no matter what it is: the framework will offer a function for this.”
More concrete: If your RIA has something like a file chooser, the file chooser test wrapper can provide a method like:
createDocument(folder, documentName)
which will do all required actions for you as for example:
- Open and select the specified folder in the folder tree.
- Wait until the folder is selected.
- Click Create Document Button.
- Wait for the tree editor to receive the focus.
- Enter the document name right into the tree.
And the GUI Map I described before evolved into Ext JS expressions mainly based on the Ext JS component manager. So in complete Ext JS notion accessing a button might look like this:
Ext.getCmp("fileDialog")
.find("itemId", "toolbar")
.find("itemId", "createDocument")
In the harness you will have a FileDialog
class which you can query for its Toolbar
which again you can query for the CreateDocumentButton
. And all of them will only know their direct containers and their very own expression. So the button will know that it can be found if the container is asked for an element with itemId = "createDocument"
.
Advantage: If the access to a parent element ever changes (and it will!) you just have to update the parent element. All child elements will automatically adopt the change.
So, this is, as always, the most basic rule to keep your UI tests maintainable:
Separate access to the UI from your test code.