Archive

Archive for November, 2009

jQuery selectors in Robot Framework Selenium Library

November 3rd, 2009 5 comments

Few months ago I selected a tool to test web interfaces: Robot Framework with Selenium Library. It allows the QA team to script test scenarios. Selenium provides a large set of keywords to drive a web-based user interface but more complicated interfaces developed using Java Script libraries like YUI and jQuery and AJAX can be harder to test. Recently I wrote a keyword to wait for YUI table to load using Java Script expression with jQuery selectors. I thought it would be great if I could use jQuery selectors to locate page elements, just like I use XPath at the moment. After doing some research I found it is possible and decided to give it a try.

I found Tellurium Automated Testing Framework that uses Selenium and jQuery selectors and a documentation page that describes how jQuery selector works.

The first thing to do is to make sure that Selenium loads jQuery. I checked out selenium library (download will also work) and unpacked the selenium-server.jar file.

cd src/SeleniumLibrary/lib
mkdir selenium-server
cd selenium-server
jar xvf ../selenium-server.jar

Then I downloaded jQuery and placed it in core/scripts directory – it’s a single Java Script file. I edited TestRunner.html andRemoteRunner.html and added a line to load jQuery just before user-extensions.js.

...
<script language="JavaScript" type="text/javascript" src="xpath/javascript-xpath-0.1.11.js"></script>
<script language="JavaScript" type="text/javascript" src="scripts/jquery-1.3.2.js"></script>
<script language="JavaScript" type="text/javascript" src="scripts/user-extensions.js"></script>
...

Then I added the following function definition to core/scripts/user-extensions.js file (RIDE replaces > and < with HTML encoded versions so those need to be converted again).

Selenium.prototype.locateElementByJQuerySelector = function(locator, inDocument, inWindow) {
    var loc = locator.replace(/&gt;/g, '>');
    loc = loc.replace(/&lt;/g, '<');
    var found = $(inDocument).find(loc);
    if (found.length == 1 ) {
        return found[0];
    } else if(found.length > 1) {
        return found.get();
    } else {
        return null;
    }
}

Next, I repackaged the jar file with ‘jar uf’ command only updating the files that I’ve changed.

jar uvf ../selenium-server.jar \
        core/TestRunner.html \
        core/RemoteRunner.html \
        core/scripts/jquery-1.3.2.js \
        core/scripts/user-extensions.js

At this point, the Selenium Library must be modified to expose “Add Location Strategy” keyword. It’s currently implemented but not visible to the user. I also added a possibility to start a different selenium-server.jar than the one distributed with the Library so I can keep my custom jar file with my test cases. I created an issue 59 and provided the patch. I hope those changes will get into the next release of the library. To simply enable the keyword, add the following method to SeleniumLibrary class in src/SeleniumLibrary/__init__.py

    def add_location_strategy(self, strategyName, functionDefinition):
        """Ads custom location strategy.
 
        'strategyName' is the name of the strategy; a prefix used when
        addressing an element.
 
        'functionDefinition' is the java script that will be called. It must
        return a DOM reference, an array with DOM references, or null.
 
        Together with the modified selenium-server.jar it can provide a new
        method of locating elements on the page. For example, a JQuery
        strategy can be added to locate elements given JQuery selector syntax.
 
        Examples:
        | Add Location Strategy | jquery | return Selenium.prototype.locateElementByJQuerySelector(locator, inDocument, inWindow); |
        | Page Should Contain Element | jquery=div.#data-table |  |
        """
        self._selenium.add_location_strategy(strategyName, functionDefinition)

Before using jQuery locators in test cases they have to be registered with Selenium. I do that in the suite setup after I open the browser window.

| Add Location Strategy | jquery | return Selenium.prototype.locateElementByJQuerySelector(locator, inDocument, inWindow); |

I can now check for existence of a table in a page (table in a div with id data-table).

| Page Should Contain Element | jquery=div.#data-table > table |
Categories: Robot Framework, Selenium, Testing Tags: