Saturday 16 June 2012

Integrating jQuery With Selenium


When testing JavaScript-heavy websites, at some point you may reach Selenium limits. A simple use case will fail. You will get ElementNotVisibleException, even though you can clearly see that element. Other times the same selector will return different results depending on the type of the browser. You can lose a lot of time searching for workarounds and hacks. Fortunately, a simple solution exists...

...but first let me introduce you to a new concept.
Not familiar with Selenium? You can grasp some knowledge here and here.

JavaScript in Selenium tests

Did you know you can execute JavaScript code inside a Selenium test? Here is how you can accomplish this using the WebDriver object:
WebDriver driver;
// create driver, i.e. driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("alert('Hello from Selenium!');");
The result is this pop-up:
You can go further and return a JavaScript object. It will then be transformed into a JavaWebElement object, on which you can execute standard Selenium methods. If on a page there was a DIV element with ID equals "example":
<div id="example">Hello from Selenium!div>
Then you could fetch that element with this piece of code:
JavascriptExecutor js = (JavascriptExecutor) driver;
String script = "return document.getElementById('example');";
WebElement exampleDiv = (WebElement) js.executeScript(script);
exampleDiv.getText(); // returns "Hello from Selenium!"

jQuery to reduce verbosity

Using pure JavaScript alone may be very verbose. jQuery can help here with its concise and elegant syntax. With jQuery you can:
  • use a great deal of selectors that work pretty much the same on every browser
  • use jQuery functions for interaction with a page (for example to do double click use the .dblclick() function)
  • easily bypass any Selenium bug by putting JavaScript code in your tests

Example scenario

Assuming we have a page for editing a list of users which looks like this:
...with HTML code looking like this:
<table id="users">
    <tr>
        <th>Nameth>
        <th>Removeth>
    tr>
    <tr>
        <td>Johntd>
        <td>
            <button onclick="removeUser('John')">
                Remove
            button>
        td>
    tr>
    <tr>
        <td>Bobtd>
        <td>
            <button onclick="removeUser('Bob')">
                Remove
            button>
        td>
    tr>
    <tr>
        <td>Franktd>
        <td>
            <button onclick="removeUser('Frank')">
                Remove
            button>
        td>
    tr>
table>
Lets try to test the following scenario:
  1. Web browser is opened.
  2. Page with a list of users is shown.
  3. User 'Bob' is removed from the list by clicking the 'Remove' button in front of his name.
Want to try the example code? You can download this github project (check theselenium3 package).

When testing JavaScript-heavy websites, at some point you may reach Selenium limits. A simple use case will fail. You will get ElementNotVisibleException, even though you can clearly see that element. Other times the same selector will return different results depending on the type of the browser. You can lose a lot of time searching for workarounds and hacks. Fortunately, a simple solution exists...
...but first let me introduce you to a new concept.
Not familiar with Selenium? You can grasp some knowledge here and here.

JavaScript in Selenium tests

Did you know you can execute JavaScript code inside a Selenium test? Here is how you can accomplish this using the WebDriver object:
WebDriver driver;
// create driver, i.e. driver = new FirefoxDriver();
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("alert('Hello from Selenium!');");
The result is this pop-up:
You can go further and return a JavaScript object. It will then be transformed into a JavaWebElement object, on which you can execute standard Selenium methods. If on a page there was a DIV element with ID equals "example":
<div id="example">Hello from Selenium!div>
Then you could fetch that element with this piece of code:
JavascriptExecutor js = (JavascriptExecutor) driver;
String script = "return document.getElementById('example');";
WebElement exampleDiv = (WebElement) js.executeScript(script);
exampleDiv.getText(); // returns "Hello from Selenium!"

jQuery to reduce verbosity

Using pure JavaScript alone may be very verbose. jQuery can help here with its concise and elegant syntax. With jQuery you can:
  • use a great deal of selectors that work pretty much the same on every browser
  • use jQuery functions for interaction with a page (for example to do double click use the .dblclick() function)
  • easily bypass any Selenium bug by putting JavaScript code in your tests

Example scenario

Assuming we have a page for editing a list of users which looks like this:
...with HTML code looking like this:
<table id="users">
    <tr>
        <th>Nameth>
        <th>Removeth>
    tr>
    <tr>
        <td>Johntd>
        <td>
            <button onclick="removeUser('John')">
                Remove
            button>
        td>
    tr>
    <tr>
        <td>Bobtd>
        <td>
            <button onclick="removeUser('Bob')">
                Remove
            button>
        td>
    tr>
    <tr>
        <td>Franktd>
        <td>
            <button onclick="removeUser('Frank')">
                Remove
            button>
        td>
    tr>
table>
Lets try to test the following scenario:
  1. Web browser is opened.
  2. Page with a list of users is shown.
  3. User 'Bob' is removed from the list by clicking the 'Remove' button in front of his name.
Want to try the example code? You can download this github project (check theselenium3 package).