From Documentation

Jump to: navigation, search




  • Author
    Gregor Schmid, Lead Developer of QF-Test and Managing Director of Quality First Software GmbH
  • Date
    May 08, 2014
  • Version
    ZK 7, QF-Test 3.5.6/4.0


Contents

Introduction

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
http://www.zkoss.org/zkdemo/tree/load_on_demand

Qfs zk tree.png

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>

The IDs of those nodes are automatically generated and thus not much use for test automation. To automate interaction with the tree you need to do quite a bit of programming to get to the correct DOM node and interact with it. It can be done, but it requires in-depth Javascript development knowledge - a kind of expertise that is different from what it takes to write the application in the first place. The above HTML also shows one of the quirks that are specific to ZK: Most clickable elements are represented as <i> nodes. This is perfectly legal, of course, but a test tool based on standard HTML without ZK-specific knowledge is most likely not aware of the fact that <i> nodes are among the most interesting ones here.

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:

Qfs zk tree qftest.png

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'".

In fact, during replay you could even skip the first three events and simply replay the last click. In case the parent nodes '1', '3' and '8' are not currently expanded, QF-Test will take care to expand them first, making sure that the node '18' is visible before clicking it. This is possible only because QF-Test "understands" the structure of the tree as a whole. Achieving the same at Javascript level is quite an effort.

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.

Qfs zk 3d compare.png

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

http://books.zkoss.org/wiki/ZK_Developer%27s_Reference/Testing/Testing_Tips

and from there to

http://www.zkoss.org/javadoc/latest/jsdoc/

Now that came as a surprise. A complete and comprehensive Javascript documentation for the client side UI of ZK - wow! From our previous experience with AJAX frameworks we had given up any hope that such a thing might exist. The framework tends to be very well documented for the server side but we always had to analyze the client side on our own so far, but the ZK client side Javascript documentation is exemplary and extremely valuable for ZK test automation. We are now able to retrieve the developer-assigned IDs at Javascript level and are going to make use of this in the next version of our ZK resolver. By the time you read this it is probably already part of QF-Test!

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

http://www.qfs.de

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 <qfs@qfs.de>.


Comments



Copyright © Quality First Software GmbH. This article is licensed under GNU Free Documentation License.
You got stuck here?
Let us know how we can improve this page
For specific questions please use the forum