advanced selenium neal ford 2
TRANSCRIPT
advanced selenium
NEAL FORD software architect / meme wrangler
ThoughtWorks®
[email protected] 3003 Summit Boulevard, Atlanta, GA 30319 www.nealford.com www.thoughtworks.com blog: memeagora.blogspot.com twitter: neal4d
Questions, Slides, and Samples
Please feel free to ask questions anytime
The slides and samples will be available at www.nealford.com
I’ll show that address again at the endSamples denoted via => document_name
What This Session Covers
Selenium’s scope
TestRunner techniques
Remote Control
Ajax
IDE
Extensions
Best practices
Selenium’s ScopeSelenium is an acceptance testing tool for web applications
Selenium tests are fragile by design
Selenium Test Runner Mode
Selenium Test
Runner
Selenium Core
Application
Under Test
The Selenium IDEFireFox extension
Not just a recorder
Intelligent field selection
Autocomplete for all common Selenium commands
Walk through tests
Debug and set breakpoints
String Matching Patterns
glob:patternMatch a string against a "glob" (aka "wildmat") pattern.
"*" represents any sequence of characters"?" represents any single character.
Glob patterns match against the entire string.regexp:regexp
Match a string using a regular-expression. The full power of JavaScript regular-expressions is available.
exact:stringMatch a string exactly, verbatim, without any of that fancy wildcard stuff.
If no pattern prefix is specified, Selenium assumes that it's a "glob" pattern.=> End 2 End Test
TestRunner Techniques
End-to-end Testing
Example of end to end testing => End 2 end Test
Always make sure you leave your application in a known good state
Generating Unique Values
The problem: you need unique user names
Solution: create user names based on time values
'fred ' + (new Date().getTime())
Data Driven TestsTest cases (and suites) don’t have to be static HTML
Verifying # of Rows in a TableAssert that nth row exists and that nth+1 does not
Use the assertXPath extension to count columns
assertElementPresent //table[@id='mytable']/tr[10]
assertElementNotPresent //table[@id='mytable']/tr[11]
assertXpath count(//table[@id='mytable']/tr) 10
Parameters and VariablesParameter and variable declarations range from simple values to Javascript evaluation
store, storeValue, and storeText store values for later access
Internally, Selenium uses a map called storedVars, keyed to variable names
store, storeValuestore( valueToStore, variableName )
Stores a value into a variable.
Variable substitution or javascript evaluation
storeValue( inputLocator, variableName )Stores the value of an input field into a variable.
storeText, storeAttributestoreText(elementLocator, variableName )
Stores the text of an element into a variable.
storeAttribute(elementLocator@attributeName, variableName)
Stores the value of an element attribute into a variable.
Variable SubstitutionProvides a simple way to access variables using ${xxx} syntax
JavaScript EvaluationYou can use JavaScript to construct whatever values you want
The entire parameter value is prefixed with ‘javascript{‘ with a trailing ‘}’
Text inside the braces is a pure JavaScript expression
Harvesting ValuesVariables allow you to harvest information from an “information only” page
Steps:
Build a page with values
On startup of the test, harvest those values
Use the variables for assertions in subsequent tests
=> harvesting values
Selenium Remote Control
Selenium Remote Control
JUnit Test
Proxy Server
Selenium Core
Application
Under Test
Interactive SeleniumStart the proxyCreate an instance of the browser
The proxy will provide a unique ID that must be used in all subsequent commandsYou’ll see a separate instance of the browser launch
Issue Selenium commandsWhen done, kill the browser instance=> Interactive Selenium
Test Code ReuseOne of the advantages of remote control
Create “helper” methods for common tasks
Login helper => DecisionDemo
When designing tests
Keep them modular
Refactor frequently
Multiple Language SupportThe Selenium IDE generates tests in a variety of languagesAll your tests don’t have to be in the same languageJava == Ruby example =>
Selenium Remote Control, Selenium Remote Control Ruby
Use the language that makes sense for the situation
DecisionsTestRunner tests can’t make deciscions
The Selenium language was designed to be strictly declarative, not imperative
In remote control, you write unit testsAllows you to make testing decisions
Firefox makes you logon, IE doesn’tDifferent roles for different users
Remote control gives you imperative tests in Selenium => Decision Demo
The Selenium IDEMore than just a pretty face!Supports multiple languages
TestRunner (declarative)Java, Ruby, C#, Python, etc. (imperative)
A round-trip tool……but only for declarative testsDon’t make the imperative plunge lightly
AjaxBecause Selenium works directly with the DOM, testing Ajax is easyTesting XmlHttpRequest =>Testing collapsable divs => End 2 End TestTesting absence of controls =>
Extending SeleniumSelenium allows you to add your own actions, checks, and locator strategies
Selenium uses naming patterns to discover extensions at run-time
ActionsAll methods in the form of doFoo are added as actionsFor each foo, and fooAndWait is created
ChecksAll assertFoo methods are added as checksFor each foo, you get assertFoo & verifyFoo
Locator StrategiesAll locateElementByFoo methods on PageBot are added as locator strategies
Locators take 2 parameters
Locator string (minus the prefix)
Document in which to search
Add a "valuerepeated=" locator, that finds the first element a value attribute equal to the the supplied value repeated.
Custom Locator
User ExtensionsBy default, Selenium looks for a file called "user-extensions.js", and loads the javascript code found in that file.
A convenient location for adding features to Selenium, without needing to modify the core Selenium sources.
This file doesn’t exist by default (you’ll have to add it)
Handy User ExtensionsAlert =>
Interactive debugger =>
GUI_Map =>
Allows you to handle auto-generated fields names more gracefully
Include =>
Check out http://wiki.openqa.org/display/SEL/Contributed+User-Extensions
Uploading FilesNormally, JavaScript permissions block you from filling in an input path for a file upload
Workaround:
Set the browser property “signed.applets.codebase_principal_support” to true
Add “netscape.security.PrivilegeManager.enablePrivilege(”UniversalFileRead”);” to selenium-api.js in function Selenium.prototype.doType
Currently only works in Firefox
Selenium Best PracticesCreate modular test methods for remote control
Allows for test code reuseEasier to refactorNot as fragile
Record acceptance testsEnd users/business analysts only have to verify it onceRegression tests catch errors
Selenium Best PracticesWrite selenium tests late in the development cycle
User acceptance tests are fragile
Require lots of refactoring
The danger is that you’ll stop running regression tests if they break too much
Questions?Please fill out the session evaluations
Samples & slides at www.nealford.com
This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 2.5 License.
http://creativecommons.org/licenses/by-nc-sa/2.5/
NEAL FORD thoughtworker / meme wrangler
ThoughtWorks14 Wall St, Suite 2019, New York, NY 10005 nford@thoughtworks.comwww.nealford.comwww.thoughtworks.commemeagora.blogspot.com