We have been using Selenium successfully as an automated tool for Acceptance Testing all releases from our outsourcing provider. Even though we have written many of the testcases in ruby, using the IDE to create testcases in Selenese has been enough in many cases. Every release we receive is tested using the old test suites to make sure the new functionality does not break existing one, this step is also called regression testing. Selenium works great for applications with an already advanced user interface that will not change significantly over time any more. Otherwise a lot of time will be spent debugging the testcases themselves. One way around this is to use a fixed id for the elements used in testing, but that might not always be possible.
Tip:If you have access to the database, create a database dump after running a test suite. If you have to do manual tests in between test suites then create a db dump before AND after. This will make your life a lot easier if your tests are dependent on previous tests which they probably will be. Now if one of the tests in a test suite fails, you just reload the database and start the test suite again.
We used Selenium and found it to work very well with our AJAX enabled website, but it took some time to get the head around the topics described below. The following examples worked in Firefox 3.6.10 and Selenium IDE 1.0.7.
The documentation was pretty useful and the API covered most other topics not found in the documentation.
Selenium IDE documentation
Selenium Selenese Commands
Selenium 1.0 API
AJAX/Javascript in general
When you are using AJAX/Javascript, the web page will most likely not actually reload. Therefore Selenium will not know if and when an element in the page is available and the verify* or assert* commands will often fail. This is where the waitFor* commands come in. For all these commands Selenium will repeatedly check whether a certain event came to pass until a set time out is reached. By default the time out is set to 30 seconds but can be manually adjusted using (surprise surprise)
setTimout( timeout in milliseconds) –> setTimeout(5000) –> sets timeout to 5s
Once set, the timeout will stay at 5s.
AJAX or “in browser” popup
Many web applications now use what we call an “in browser” popup, this is NOT a smaller new browser window and NOT a Javascript alert. Most of the time it is a hidden DIV element at a relative or fixed position that is shown and hidden using javascript and might be populated with data from the server using AJAX. It is very often used for data entry and therefore will have to be tested with Selenium.
- Use waitForVisible if the element’s CSS attributes include “visibility:hidden” or “display:none”.
- Use waitforElementPresent if the element did not exist before. This will not work for the above situation because the element itself is present, even though it is not visible.
Tip:use waitFor commands in sequence if you are waiting for an element in a container. For example you have to test an AJAX action that populates a hidden DIV with a page from the server that contains input fields and then makes the DIV visible. As part of the test you most likely will have to populate these inputs fields. In that case use waitForVisible for the DIV container first and then use the waitForElementPresent for the first input field. Even though Selenium verified that the DIV is now visible, it still is not a guarantee that the browser already loaded the form with the inputs fields from the server. So the test will most likely behave slightly erratic, sometimes it passes and sometimes it will fail. Using a sequence of waitFor commands will make sure that the elements are available at the time of the test step.
Javascript alert boxes/confirmations
Javascript alerts are a bit of a problem for Selenium and there are even situations where the box has to be clicked manually. (From the documentaiton: Selenium does NOT support JavaScript confirmations that are generated in a page’s onload() event handler. In this case a visible dialog WILL be generated and Selenium will hang until you manually click OK.)
But most of the time it is possible to deal with this pesky little alert boxes. When recoding the test using Selenium IDE the alert boxes appear as normal and the IDE will happily record a “assertConfirmation” command, but when running the test, no alert box shows up and the test often fails. It is important to know that alert boxes are NOT shown when running the test as noted in the Selenium documentation. And replacing assertConfirmation with waitForConfirmation most of the time allows the test to pass.
All commands use a positive confirm, so if you want to test the negative confirmation use chooseCancelOnNextConfirmation BEFORE the action that results in the alert box.
Drag & Drop
Even complicated actions like drag and drop can be implemented using the Selenium IDE only. In our case we had the following setup to test.
- Two DIVs side by side with ids “account” and “team”, the “account” DIV containing a table of account users not in a project team and the “team” DIV containing the table of the project team users.
- The users were distinguished using their unique email address and the table position for a specific user is dynamic in both DIVs.
- Dragging a user from the “account” into the “team” DIV also opened an “in browser” popup to choose the project roles for that user.
- Once the user was moved over in the “team” DIV, we needed to check that the email address was in the table of the “team” DIV.
| Command |
Target |
Value |
Comment |
| mouseDown |
//div[@id='account']/table/tbody/tr[1] |
|
Click the left mouse button over the first user in the table (uses an Xpath locator) |
| storeText |
//div[@id='account']/table/tbody/tr[1]/td[2] |
email |
Store the email address of the user in the variable “email” |
| mouseMoveAt |
team |
|
Move the mouse over the the “team” DIV (using the id as locator) |
| mouseUp |
team |
|
Now release the left mouse button over the “team” DIV |
| waitForVisible |
popup_div |
|
Wait for the “in browser” popup “popup_div” to become visible |
| click |
//input[@id='roles_' and @name='roles[]‘ and @value=’4′] |
|
Tick a checkbox for the user to get that role in the team |
| click |
project_user_submit |
|
Press the submit button of the form for the roles. This also closes the “in-browser” popup |
| echo |
${email} |
|
Just for debugging, show the value for the variable “email” |
| waitForText |
//div[@id='team']//a[text()='${email}'] |
${email} |
Now wait for the user with the unique text value “email” to appear in the “team” DIV |
Tip:Don’t move the mouse when running a test that contains mouse movement commands, otherwise your mouse movements will interfere with Selenium and the test will very likely fail.
Tip:Use the echo command to check your variables in the log (works if set to info)