Testing ZK Applications at Business Level with QF-Test
Gregor Schmid, Lead Developer of QF-Test and Managing Director of Quality First Software GmbH
May 08, 2014
ZK 7, QF-Test 3.5.6/4.0
When developing an application with ZK you've got a comprehensive, easy to use API at your disposal that enables you to create a rich user interface with all of the common high-level components that users are familiar with from desktop applications. You don't have to rack your brains about how to implement something like a tree view in the browser's DOM – the ZK framework takes care of that for you.
However, when it comes to automated testing of such an application, you suddenly get confronted with all the details that ZK was shielding you from. Even a simple tree view is created from hundreds of small <DIV> and <SPAN> nodes arranged in a table. The following video vividly demonstrates the explosion of complexity generally seen in AJAX user interfaces using Firefox's 3D view – as the saying goes: you may at times no longer see the wood for the trees: http://www.qfs.de/en/qftest/web-gui-testing-reduction-of-complexity.html
An example for the complexity of a simple ZK user interface
Now let's dive down into the details of a ZK GUI and take a closer look at a very simple tree from the ZK demo at
The Firefox inspector shows that the tree is implemented as a <TABLE>:
<table id="sLIQg-cave" width="100%" style="table-layout: fixed;"> <tbody id="sLIQg-rows" class="z-treechildren"> <tr id="sLIQn" class="z-treerow"> ... </tr> <tr id="sLIQv" class="z-treerow"> <td id="sLIQw" class="z-treecell"> <div id="sLIQw-cave" class="z-treecell-content"> ... </div> </td> </tr> ...
A tree node is a <TD> with the following content:
<td id="sLIQw" class="z-treecell"> <div id="sLIQw-cave" class="z-treecell-content"> <span class="z-tree-line z-tree-spacer"/> <span id="sLIQv-open" class="z-tree-icon"> <i id="sLIQv-icon" class="z-icon-caret-down z-tree-open"></i> </span> <span class="z-treecell-text"> 3 </span> </div> </td>
How QF-Test addresses the problem
QF-Test tries to do for the tester what ZK does for the developer: Hide all the little details and provide high-level access directly to the tree. Before explaining how that is done, let's take a look at the result. Recording a few mouse clicks with QF-Test that open the tree nodes '1', '3' and '8' to finally click on '18' leads to four simple mouse clicks that QF-Test represents as follows:
The coordinates (-1001,0) are "magic" values telling QF-Test to target the expander of the node. What's interesting is the representation of the tree nodes, e.g. "zkoss.org.zbody.tree@/1/3". The first part, "zkoss.org.zbody.tree" is an internal id assigned by QF-Test to the representation of the tree and the "@/1/3" is QF-Test item syntax for "A tree node labeled '3' below a tree node labeled '1'".
The following 3D image illustrates the difference between the original DOM structure of the tree demo page and the component hierarchy that QF-Test reduces it to.
So how does QF-Test do that? Of course this doesn't work out of the box. QF-Test has a generic mechanism of so-called Resolvers that implement high-level components from different kinds of DOM nodes. There is a particular Resolver that handles tree widgets and works for many different AJAX toolkits based on a lower-level, toolkit-specific mapping that mostly consists of identifying the key DOM nodes and mapping them to generic classes.
For ZK the following approach was taken: The CSS classes in ZK are very consistent and make an excellent basis for mapping to generic classes. Some examples are z-tree → Tree, z-treecell → TreeNode or any of [z-tree-ico,z-tree-icon,z-tree-open,z-tree-close] → TreeNodeExpander.
Such mapping is sufficient for QF-Test to take care of the rest. The tree structure with its parent->child relationship is then reverse-engineered based on the indentation of the nodes.
All in all the implementation of the ZK Resolvers for QF-Test was pretty straightforward. As with other AJAX toolkits the number of DOM nodes generated by ZK is large and nesting of those nodes can get very deep, but fortunately this can all be filtered. The HTML generated by ZK is relatively clean and the structure is consistent with few surprises, the use of <i> nodes for clickable elements mentioned above is harmless compared to some of the peculiarities we've seen elsewhere.
Room for improvement? Yes, but for us – ZK is already there…
When I started off writing this small talk I meant to elaborate on how nice it would be to have a simple way for developers to assign IDs to components and have those IDs passed through to the respective DOM nodes. Though QF-Test's component recognition is already excellent, being able to make use of developer-assigned IDs can improve any test, provided those IDs are consistent and well chosen. Unfortunately the ID attributes that ZK creates automatically for the DOM nodes are of no use for component recognition.
I thought that implementing an IdGenerator was the only way and that this is rather complex and might not have the desired result of creating IDs that remain valid as the application evolves. Our experience is that if there is an extra effort involved in improving testability of an application it is often simply not done. Trying to learn more about IdGenerators and what we can do to improve the situation, I came across
and from there to
See for yourself
Thank you for taking the time to read this through. If you have a ZK application that needs testing I'd like to invite you to try out QF-Test on your own. It is available for download without registration from
After installation, create a startup sequence for your application using the Quickstart Wizard from the >>Extras<< menu and run the sequence to launch the browser. The ZK framework should be recognized automatically so that you can experiment with recording and replay at a very high level of abstraction. For any help or in case of questions feel free to contact us at <firstname.lastname@example.org>.
|Copyright © Quality First Software GmbH. This article is licensed under GNU Free Documentation License.|