Nuxeo Core Developer Guide

Selenium tests

Updated: December 16, 2024

Nuxeo is using a tool to run selenium tests on a given server, see documentation at https://github.com/nuxeo/tools-nuxeo-ftest

Selenium Documentation

Helpful links: http://seleniumhq.org/documentation/

Commands reference: http://release.seleniumhq.org/selenium-core/1.0.1/reference.html

Firefox Plugins

Here are some Firefox plugins that make life easier writing Selenium tests:

Structure of Nuxeo Test Suites

The Nuxeo test suites are located in subdirectory tests/ and named tests.html, suite1.html and suite2.html.

tests.html has been cut in two for automated testing: THINK OF UPDATING ALL FILES WHEN ADDING/REMOVING tests.

Note that the tests are currently not very "unit": some tests will require previous tests to be run to succeed.

Generic Advice When Writing Tests

  • Have a look at selenium commands to see what is available.

  • Write small test cases, and try to make them as unit as possible. Do not forget to set a timeout at the beginning of your test (it default to 3000ms may not be enough) and to start and end the test by logging out of the nuxeo application.

  • Be specific when testing an element: a vague xpath reference may trigger a false error if the HTML page slightly changes. If you can't be specific, then page rendering should be changed to ease this process.

  • Handle ajax requests properly: if the test cannot detect correctly when the ajax call is finished, it may lead to "heisenbugs", e.g. tests alternatively failing or succeeding with no apparent reason.

 

1. when triggering an ajax call through a4j or richfaces JSF libraries, the following commands have been made available in the nuxeo suites user-extensions.js file: "watchA4jRequests" and "waitForA4jRequest". "watchA4jRequests" has to be called before any command that will trigger an ajax call, it does not take any parameters. "waitForA4jRequest" has to be called after the command that will trigger an ajax call, it takes a timeout as parameter.

Sample usage:

<tr>
  <td>watchA4jRequests</td>
  <td></td>
  <td></td>
</tr>
<tr>
  <td>typeKeys</td>
  <td>//input[@name='createUser:nxl_user:nxw_groups_suggest']</td>
  <td>members</td>
</tr>
<tr>
  <td>waitForA4jRequest</td>
  <td>10000</td>
  <td></td>
</tr>

WARNING: The "typeKeys" command has a bug that simulates the "ALT" key when using the "y" character (see http://jira.openqa.org/browse/SIDE-309) so you should avoid this character in suggestion keywords.

2. when triggering a remote call using jQuery or prototype Javascript libraries, the following command has been made available in the nuxeo suites user-extensions.js file: waitForJSQueries. It takes a timeout has parameter.

Sample usage:

<tr>
  <td>waitForQueries</td>
  <td>100000</td>
  <td></td>
</tr>

3. when triggering any other call (Javascript call with Seam remoting calls for instance), using the Selenium command "waitForCondition" with appropriate javascript testing is usually enough to test that the ajax response has been received. Commands "waitForEditable" or "waitForTextPresent" may also be helpful.

Sample usage:

<!-- wait for table to disappear -->
<tr>
  <td>waitForCondition</td>
  <td>selenium.browserbot.getCurrentWindow().document.getElementById('editGroup:nxl_group:nxw_members_list:2:nxw_members_listItem') == null</td>
  <td>10000</td>
</tr>

How to Get an Element When No ID Is Available

(taken from http://lawrencesong.net/2008/01/selenium-element-locators/)

<a href="link url">Link Text</a> -> link=Link Text

Get Element With the Element Text:

<a href="link url">Link Text</a> -> //a[text()='Link Text']

Get Element With Part of the Element Text:

<a href="link url">Link Text</a> -> //a[contains(text(), 'ink Tex')]

Get Element With an Attribute:

<a href="link url">Link Text</a> -> //a[@href='link url']

Get Element With Two Attributes:

<input type="text" value="value"/> -> //input[@type='text' and @value='value']

Sometimes This Command Will Succed:

<td>click</td>
<td>dashboardDocumentProcessTable:j_id130</td>
<td></td>

when this one will fail:

<td>click</td>
<td>//input[@id="dashboardDocumentProcessTable:j_id130"]</td>
<td></td>

When trying to debug what's happening on the server, it may be useful to print out the rendered HTML in the page. The following command can be used:

<tr>
  <td>storeEval</td>
  <td>selenium.browserbot.getCurrentWindow().document.body.innerHTML</td>
  <td>innerhtml</td>
</tr>
<tr>
  <td>echo</td>
  <td>${innerhtml}</td>
  <td></td>
</tr>