Selenium for Automation – Testing Axial-Style Part 1

The challenge with testing is no different than most: allocating resources. Its hard to sacrifice resources for testing at the cost of new features and still feel a sense of accomplishment – especially when such a sacrifice needs to be made every time you release. At Axial we release every day and have come to realize that such sacrifices need to be made consistently in order to maintain a top quality product. We recognized the need to make our testing efforts more reusable. We accomplished this by doing what the corpus does best: build. From this we built Axium, a test automation suite that is easily executed, understood, maintained and configured. This is the first of a series of posts that shows how we built Axium and contains the following independent parts:


1. Selenium – For test automation

2. The Page Object Model – For test maintainability

3. Pytest – For test configuration

4. Axium – Bring it all together

Those testing web apps using Python will benefit the most, although topics covered are applicable to most languages and testing needs. 

Selenium


Selenium is a test automation tool that comes in two flavors:


1. Selenium IDE – a Firefox extension that simulates browser interactions and optionally records them


2. Selenium WebDriver – a to run interactions in the browser programmatically. Selenium WebDriver is the successor of Selenium Remote Control.


Part 1 covers how Selenium works using the IDE, WebDriver is covered in part 2.

Installing Selenium IDE


1. From Firefox, visit this download page and click on the latest version of Selenium IDE

2. Firefox will detect this is an add-on and ask for permission, click “Allow”

3. Open with Tools -> Selenium IDE

4. There are also a bunch of very useful plugins on Selenium’s download page 

To install Selenium WebDriver


pip install selenium

Example


Following is an example of creating a test case to get the weather at weather.com


1. Open the Selenium IDE from Firefox using Tools > Selenium IDE


2. Click Record (red circle on top right-hand corner


3. Switch back to your Firefox browser and …


a. Go to www.weather.com


b. Enter your location in the search bar


c. Click search


4. Switch back to Selenium IDE and …


a. Click Record again to stop recording


b. Run your test case by clicking “Run Test Case”


 You should see something similar to the screenshot below. Selenium IDE shows the different commands that makeup the test case. Each command does the following:

1. Open the root directory of the Base Url (www.weather.com)


2. Click on the element with an ID of typeaheadBox (the search box)


3. Enter “New York, New York” into the search box


4. Trigger the click() event for each div with a class of “wx-searchButton”. Wait for the page to respond before continuing (although we don’t continue in this example).


5. To verify correct output:


a. Highlight some expected output


b. Right click and select “Show All Available Commands” -> “AssertTextPresent was added successfully”




Selenium Constructs


Commands


Commands have three parts: the name of the command, the target and the value.


Actions – commands that perform operations, such as navigating a page


Accessors – are commands that allow you to get and set variables


Assertions – are commands that allow you to verify expected behavior

Locators


Element Locators are used to specify which HTML elements a command should operate on. There are many different and convenient ways to locate elements. Those who prefer jQuery selectors should check out Sizzle.

Sizzle


Sizzle is a library that allows you to select elements with jQuery and CSS 3 selectors in Selenium.

Installing Sizzle


1. Download Sizzle on GitHub

2. Extract to a permanent location

3. Create user-extensions.js with the following contents:

PageBot.prototype.locateElementBySizzle = function(locator, inDocument) {

var results = [];
 window.Sizzle(locator, inDocument, results);
 return results.length > 0 ? results[0] : null;
}

4. In Selenium IDE, select Options -> Options and add sizzle.js and user-extensions.js to "Selenium Core Extensions"

5. Restart Selenium IDE 

Test installation with by executing the verifyElementPresent command with a target of sizzle=body and a value of true. When you execute the command it should highlight green, not red.

Patterns


Patterns can be used to locate text with regular expressions or wildcards. The majority of commands that accept patterns are assert and verify. There are some good examples here.

Variables


Variables are set with any of the store commands and can be accessed with ${var_name} anywhere text is accepted.

Real-World Examples


Testing via Django messages.info


Recording a test case that creates a Company through our admin interface is straightforward – creating a User for that Company is not. How do we know the ID of the Company that was just created? In this case we are lucky because our admin displays a message in the form of “The company ‘8528’ was added successfully.” We can grab the Company ID from this message using the storeEval command with the following JavaScript as the target:

window.document.getElementsByClassName('info')[0].innerHTML.match('\"([0-9]*)\"').pop()

Example of a Weak Selector


These Selenium commands fill out a form capturing historical financial information. Do you see anything that could be improved in order to make this more flexible over time?



A better test case would not explicitly target years by matching inputs with an ID of id_*-revenue and id_*-ebitda. This prevents the test case from failing when the year changes.

iframes


Selenium allows you to select iframes with the selectFrame command.

Waiting for ajax requests


If you want your test case to wait for an ajax request then call waitForElementPresent with the identifier of whatever it is you are ultimately looking for. The following test script sends a message to another user by (1) waiting for an ajax response with a send button (i.e. a button whose id starts with “send-”) to complete and then (2) clicking the button to send.