Mary Jo Sminkey!
• 20+ Years in Web Development!
• ColdFusion Developer since CF 3.0 Release by Allaire!
• Author of the e-commerce application CFWebstore!
• Currently working for CFWebtools as the Lead Developer for a large e-
commerce website selling classic car parts (Classic Industries)!
• Hobbies include dog training and showing, photography, playing music,
baking, board games, scrapbooking, origami, and more!
• Automates Testing Applications in the Browser!
• Will simulate users interacting with the site and find bugs that unit tests
• Can use even for legacy sites that may not work with unit testing!
• Portable across many browsers and coding platforms!
• Popular so easy to find help and plugins, etc. !
• Easy to get started with but can also handle very advanced and complex
• Includes IDE (Firefox Plugin) and Web Driver (runs tests on Selenium Server)!
• We will focus today on building tests to run in the IDE!
• Easy for newbies to learn, uses simple HTML syntax !
• Plugins available that help debug your scripts!
• User extensions can also be added to extend the language (loops, if/else if,
etc) although there are caveats to be aware of.!
• Many tools available to convert IDE scripts to run on Web Driver (cfselenium)
Some IDE Tips
• Set your default timeout to something reasonable!
• To run an individual test, use keyboard shortcut “X” !
• If your site uses popup windows, be sure to configure FF to allow them for the address!
• The “Find” button can be helpful to highlight the target element, but don’t rely on for
most XPath locators!
• The speed slider can be useful to debug a fast-running script, but should not be used
for tests that don’t pass at full speed.!
• Some Firefox plugins may cause Selenium tests to work incorrectly (like form fillers)
so you may want to have a separate FF profile specific for your testing.
• Download at http://docs.seleniumhq.org/download/!
• Favorites !
• Save and quick-launch your favorite test suites!
• Test Results!
• Generates reports of test and suite results after running !
• Highlight Elements!
• Highlights target elements on the page as your tests run!
• Power Debugger!
• Adds the Pause on Fail button !
• Stored Variables Viewer!
• View and delete stored variables in the IDE!
Developing a Testing Plan
• What makes money (or provides value) most for the website?!
• Which pages are visited most often?!
• Which browsers are used most often? !
• What areas have been the most common to experience bugs? !
• If other test methods in place (unit testing, etc.) what types of things
are not tested by these?
Goals For Tests
• Robust, not brittle!
• Don’t rely on data that changes !
• Can run on multiple environments!
• Will run at any speed without errors !
• Start simple and make it work, then refactor adding more
capability and tests
Creating Selenium Tests
• Macro Recording Feature!
• Useful to get started quickly!
• Often creates very unreliable, brittle locators!
• Manually writing tests in HTML!
Verifying Text on the Page
• verifyText(Not)Present/assertText(Not)Present (depricated)!
• Checks that the text exists/does not exist on the webpage, with no element
• Checks that the text given is found/not found in the element specified!
• Checks that the page HTML Title tag matches/does not match the text
Verifying Elements on the Page
• verifyElement(Not)Present/assertElement(Not)Present !
• Checks that the element designated can/can not be located on the page!
• Checks that the given table designated is found/not found on the page!
• Checks that the specified attribute of an element matches/does not match the
Verifying Form Elements
• Checks if a toggle element (checkbox/radio button) is in a checked/ unchecked
• verify(Not)SelectOptions/assert(Not)SelectOptions !
• Checks if the array of options for a selectbox matches/does not match a given
• verify(Not)Selected/assert(Not)Selected (depricated)!
• Checks that the option matching the pattern is selected (or not selected)
Verifying Form Elements, cont.
• verify(Not)SelectedId(s)/assert(Not)SelectedId(s) !
• Checks that the ID(s) of the selected option(s) matches/does not match the value(s)!
• verify(Not)SelectedIndex(s)/assert(Not)SelectedIndex(s) !
• Checks that the index(es) of the selected option(s) matches/does not match the
• Checks that the label(s) of the selected option(s) match the pattern !
• Checks that the value(s) of the selected option(s) match the pattern!
Checks if a form element is/is not editable, ie hasn’t been disabled!
• Checks that the designated cookie is found/not found on the client!
• Checks all the cookies on the page !
• Checks that the value of the specified cookie matches/does not match the
• Checks that the last JS alert matches/does not match the text pattern!
• Checks if a JS alert occurred/did not occur !
• Checks that the last JS prompt matches/does not match the text pattern!
• Checks if a JS prompt occurred/did not occur
Let’s Talk Locators!
• identifier=id: Select the element with the specified @id attribute. If not found, look for a
match with @name. (default)!
• id=id: Select the element with the specified @id attribute.!
• name=name: Select the element with the specified @name attribute.!
• May be optionally followed by one or more element-filters, e.g. value!
• link=textPattern: Select the link element which contains the text matching the specified
• css=cssSelector: Select the element using css selectors. !
• xpath=xpathExpression: Locate the element using an XPath expression.
Locator Examples: CSS Selectors
This Selector: Finds
css=p first paragraph tag in the document
css=a first link in the document
css=a#id3 link with the matching id element
css=#linkTest :link link inside the element with the id of linkTest
css=a[name^="foo"] link with a name attribute beginning with ‘foo’
css=span#firstChild + span span that follows the span with the id of firstChild
css=div#childTest :last-child last child element of the childTest div
css=div#nthTest :nth-child(2n) 2nd child element of the nthTest div
css=div#linkTest a first link inside the linkTest element
css=a[class~="class2"] the link that has a class containing the word ‘class2’
css=input[type="text"]:disabled first text input element that is disabled
css=input[type="checkbox"]:checked first checkbox element that is checked
css=a:contains("foobar") link that contains the text foobar
css=a[name*="foo"][alt] link with a name attribute that contains foo and has an alt attribute
Locator Examples: XPath Selectors
This Selector: Finds
//img[@alt='The image alt text'] image tag with the given alt text
//table[@id='table1']//tr/td 4th row, second cell of table1
//a[contains(@href,'#id1')]/@class the class of the link with an href of ‘#id1’
//*[text()="right"] the element with internal text of ‘right’
//input[@name='name2' and @value='yes'] input field with name of ‘name2’ and value of ‘yes’
//input[@type='submit' and @name='send'] submit button with name atribute of ‘send’
//input[@type='radio' and @value='1'] radio button with value of 1
//table[@id=’table1’]/tbody/../td/a@href The link location for the second link in the first table cell
of table1//*[contains(text(),'Sample Text')]/..//a Locates the element that has the text "Sample
Text", then goes up a level from there and finds the//td[contains(text()),’Label’]/following-sibling::td/a Locates the table cell with the text "Label" and gest the
link in the next table cell over
So let’s look at some tests!
Tests located in:!
• Opens a specified URL!
• Opens a popup window; select the popup Window!
• Checks/unchecks a toggle button (checkbox/radio) !
• Selects an option from a drop-down using an option locator!
• Submits the specified form!!
• type! !
• Sets the value of an input field, as if typed into
More Keystroke Actions
• Click on a link, button, checkbox or radio button (and wait for the next page to load)!
• Click on a link, button, checkbox or radio button based on specific coordinates (and wait
for the next page to load)!
• Simulate triggering an event, along with its corresponding “onevent” handler!
• Move the focus to the specified element!
• Simulates a user pressing and/or releasing a key!
• Simulates keystroke events on the specified element
Tips on Testing Keystrokes
• Sending keystrokes don’t always trigger the corresponding “onevent” JS
methods. You can use the “fireEvent” to make sure the onevent gets fired. !
• The ‘typeKeys’ is a convenience way of not having to enter keydown/keyUp/
keyPress events for each character, however this command often does not have
a visible effect on the page. You may need to combine it with a ‘type’ command
to both have the text visible in a form as well as send the keystroke events. !
• The ‘type’ command can also be used to set the value of selectboxes,
checkboxes, etc. To do this, set the value to the value of the option selected,
versus the visible text.
Selenium Actions: Wait
• Use after any action that causes a new page to load. Replaces “andWait” !
• Waits for a popup window to appear and load up!
• Wait until a specific element is found/not on the page!
• Wait until a specific element is visible/not visible on the page!
• Wait until a specified option is selected !
• Wait for specified text on an element !
• Specifies the amount of time to wait for an action to complete
Tips On Using Waits
• These are going to be critical in testing pages utilizing Ajax!
• When used successfully you should never need to use a “pause” command in your
tests to get around tests failing for not waiting for Ajax code to complete.!
• Use the ‘setTimeout” for page loads or “wait” actions that will take longer typically
than the default timeout. !
• Global Ajax handlers can be very helpful for managing how your pages with Ajax
perform and thus make writing tests a lot simpler. For instance, we disable forms
during Ajax calls and display a “loading” animation. Testing that the animation is not
visible is a nice extra check on pages using Ajax to make sure that the code has
completed before continuing.
• Available in Web Driver 2 or as a Selenium IDE user extension!
• Implicit Waits tell Selenium to automatically wait to continue until the locator or
condition is met. !
• Adds the commands setImplicitWaitLocator to set implicit waits based on the locator
and setImplicitWaitCondition to set implicit waits based on a specific condition (for
example, any test for no running Ajax transactions). !
• Keep in mind that most tools to convert from IDE scripts to Selenium RC (web
driver) code are not going to support user extensions.
• store (depricated) / storeExpression!
• Stores the expression in the specified variable!
• Stores the text inside the element specified!
• Stores the value of an element attribute!
• Stores the current page URL!
• Stores the HTML Title of the page
Storing Form Data
• Stores the selected Id(s) of the specified selectbox!
• Stores the selected index(s) of the specified selectbox!
Stores the selected index(s) of the specified selectbox!
Stores the selected value(s) of the specified selectbox!
• Stores all options labels in the specified selectbox!
• Stores the value of an input field!
• Gets whether a checkbox/radio button element is checked
Storing Alerts, Cookies
• Stores the message of a JS alert dialog in the specified variable !
Stores the message of a JS confirmation dialog !
Stores the message of a JS question prompt dialog!
• Stores the value of a cookie
Handling Alerts & Prompts
• Use this to consume the alert and remove it from the browser!
• Use this to consume the confirmation dialog and remove it from the browser!
• Use this to consume the prompt and remove it from the browser
More on Alerts and Other Dialogs
• The proper sequence of commands is to use the “onNext” command as appropriate
for the next item, then the action that will generate the dialog, then the command to
“consume” it. !
• Note that in Selenium IDE you typically will not see JS alerts and dialogs in the
• For newer sites, you may want to consider switching to jQuery or other modal
dialogs that are handled by making page elements visible/not visible. These are
typically more reliable and easily handled in Selenium tests. !
• For these dialogs, you typically will be using “waitForElementVisible” and/or
“waitForText” commands to determine when the dialog is showing and the
corresponding “Not” version to determine when it’s been removed.
Working with Cookies
• Adds a new cookie, with path and domain of the page under test
• Deletes all cookies visible to the current page!
• Delete a named cookie with the specified name and domain
• Prints the specified message to the log, also helps debug when viewing the list of
• captureEntirePageScreenshot !
• Not widely supported but useful for grabbing a screenshot in your tests!
• Briefly changes the background of the specified element to yellow. Similar to the
Highlight Elements plugin!
Let’s Look at a Real Site
Classic Industries !
• Large ecommerce site with 300,000+ product inventory!
• Heavy use of jQuery and Ajax!
• Active development in process so frequent updates to production!
• Some critical areas include product search, user functions and shopping cart/checkout
• Search results always changing due to inventory/stock changing!
• Different messages, checkout process based on type of product(s)
• Creating user accounts rely on unique email addresses!
• Multiple server environments to test on, some using SSL !
• Dev/staging environments already handle some common issues like
test orders, PayPal sandbox usage, etc.
Handling Dynamic Site Data
• Our solution here was to create a page for adding “test products” to use!
• This page runs stored procedures that are only available on development and staging
• The test products are created with specific attributes to make them easy to locate in
• The form allows for creating all the different types of products that we will need to test
• We then store the created product numbers that are output by the test data creation
form to use in our tests
Generating Unique Users
• We wanted to create users with a real email address in order to verify email sent by
various site actions.!
• The site normally does not remove users once added, this is a function handled
outside the website, but an option might be to add a Delete User function that would
run after the tests complete. !
• Instead we decided to rely on a trick involving gmail accounts. !
• A gmail address can be modified with a plus sign (+) and random string of characters,
and will email to the same base account address. !
• So for instance, I can use my email account “firstname.lastname@example.org” and add a
random string of characters and use that for a unique email address on the website
Running Test Suites on Different Servers
• Both the IDE and the tests themselves allow for a baseURL!
• However, it can be tedious to have to change these anytime you want to run on a
• Instead, we set up a “setEnvironment” file for each server that creates stored variables
for our base URL, SSL URL, any other settings unique to that environment, etc.!
• All “open” commands or “assertLocation” commands append the baseURL or sslURL
• We then run this setEnvironment as the first test for our suite for that server. !
• Can include variable settings for commonly used items in our tests
More Problem-Solving: Whitespace
• Most of the assertions for text will treat whitespace as part of the string. !
• Where possible, consider updating your HTML to remove unnecessary whitespace.!
• Selenium supports Regex which can be a good option particularly when you are trying
to store data and there may be whitespace in the element:!
• parseFloat(storedVars['partprice'].replace(/[^0-9-.]/g, ''))!
• For assertions, you can use contains() to search anywhere in the text for matches:!
• //*[contains(text(),'Sample Text')]/..//a!
• Alternatively you can use “normalize-space” to strip leading and trailing spaces:!
• //td[normalize-space(text())='My Cell Contents']
More Problem-Solving: CAPTCHA
• We prefer to use cfformprotect and this is one area it will greatly help you in not having
to deal with Captchas in your tests!!
• Most ideal is to set up a test setting for the captcha for your dev/staging environment
that will return a known value!
• If you are using a 3rd party captcha system that does not have a method for testing,
you may want to swap it out for a different one that can be configured as above in test
• A last resort might be to use JS prompt for the tester to enter the captcha (use
storeEval to create a prompt and store the result in a variable that can then be used to
type in the captcha)
Building a Complete Test: Checkout Test
1. Set up environment !
2. Create stored variables to hold a test user’s contact data, etc. !
3. Add some test products to order. !
4. Search for test products and add to the shopping cart. !
5. Create a user account and login to start checkout!
6. Enter shipping address and submit form!
7. Enter billing address and payment and complete order!
8. Verify order confirmation page