Selenium vs. ZK

Testing ZK applications using Selenium can be a drag. Selenium offers a lot of tool to test traditional request-response cycle applications. But it relies heavily on stable element IDs and submitting whole forms.

ZK, on the other hand, sends just a skeleton page to the browser and from then, builds everything with JavaScript. Instead of posting a whole form, it submits individual field values (to trigger validation). And it assigns random IDs to reach element.

At first glance, the two don’t seem to be a perfect match. But there are a couple of simple tools that will make your life much more simple.

Getting Stable IDs for Tests

One solution here is to write an ID generator which always returns the same IDs for each element. But this is tedious, error-prone and sometimes impossible.

A better solution is to attach a custom attribute to some elements which doesn’t change. A beacon. If you have a central content area, then being able to find that will make your life much more simple because whatever else you might seek – it must be a child of the main content.

To do that, add a XML namespace:

    <zk xmlns:cl="client" xmlns:ca="client/attribute">

to the top of your ZUL file, you can now use a new attribute ca:data-test-id="xxx" to set a fixed attribute on an element. In Selenium code, you can now locate this element using this code:

    By.xpath( "//div[@data-test-id = 'xxx']" )

I suggest to use this sparingly in order not to bloat your DOM. But a few of them for fast moving targets will make your tests much more stable.

Debugging the DOM

Sometimes, your life would be much more simple if you could see what the DOM was when your test failed. Here is a simple trick to get a HTML fragment from the browser:

    protected JavascriptLibrary javascript = new JavascriptLibrary();

    public String dump( WebElement element ) {
        return (String) javascript.executeScript( driver,
            "return arguments[0].innerHTML", element );
    }

You can now use JTidy and JDOM to convert the fragment first into W3C XML nodes and then into JDOM elements:

    public org.w3c.dom.Document asDom( WebElement parent ) {
        String html = dump( parent );
        Tidy tidy = new Tidy();
        tidy.setShowWarnings( false );
        tidy.setErrout( new PrintWriter( new NullOutputStream() ) );
        org.w3c.dom.Document dom = tidy.parseDOM(
           new StringReader( html ), null );
        return dom;
    }

    public static org.jdom2.Document asJDOM( org.w3c.dom.Document content ) {

        // JDOM chokes on: org.jdom2.IllegalNameException: The name "html PUBLIC "-//W3C//DTD HTML 4.01//EN"" is not legal for JDOM/XML DocTypes: XML names cannot contain the character " ".
        Node docType = content.getDoctype();
        if( null != docType ) {
            content.removeChild( docType );
        }

        DOMBuilder builder = new DOMBuilder();
        org.jdom2.Document jdomDoc = builder.build( content );

        return jdomDoc;
    }

Another great use case for this is a default exception handler for tests which saves a screenshot and a copy of the DOM at the time a test fails. No more guessing why something didn’t happen.

2 Responses to Selenium vs. ZK

  1. nikos101 says:

    If we go with ZK big time then I’ll be coming back to this post!

  2. Great tip, thanks. Using the client attributes for this is a good idea that saves much time and removes the need to implement a custom IDGenerator or similar.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s