selenium 101
TRANSCRIPT
CUPCAKE
Manual Test
Automated GUI Tests
Automated Integration Tests(API, Component)
AutomatedUnit Tests
Manual testers
Automated GUItesters
Developers
TESTING PYRAMID
AutomatedGUI tests
Automated API tests
Automated Integration tests
Automated Component testsAutomated Unit tests
ManualSession
Based Testing
Functional testsExamplesStory testsPrototypesSimulations
Exploratory testingScenarios
Usability testingUAT
Alpha / Beta
Unit testsComponent test
Performance & Load testingSecurity testing
“ility” testing
Business facing
Technology facing
Supp
ortin
g th
e te
am Critique productAutomated & manual
Automated
Manual
Tools
AGILE TESTING QUADRANTS
Q2
Q1 Q4
Q3
WHAT IS SELENIUM?• Suite of tools
• Automates browsers
• Testing purposes
• Boring web-based administration tasks
TOOLS - SELENIUM IDE• Selenium IDE
• Firefox extension
• Record and playback interactions
• Use it to
• Create quick bug reproduction scripts
• Create scripts to aid in automation-aided exploratory testing
TOOLS - SELENIUM RC• Selenium Remote Control
• Server
• Automatically launches and kills browsers
• Acts as a HTTP proxy for web requests from them
• Client libraries
• for your favourite computer language
• Deprecated
TOOLS - SELENIUM WEBDRIVER• Successor to Selenium RC
• Driving a browser natively
• Accepts commands > browser
• Sent in Selenese or Client API
• Using a browser driver
TOOLS - SELENIUM GRID
• Web browsers on remote machines
• One server acts as a hub
• Tests contact hub to access browsers
• Running tests in parallel
SCRIPT SYNTAX• Command + 2 parameters
• Not always required
• Parameters
• Locator
• Text pattern to verify
• Text pattern or variable to insert
LOCATOR - IDENTIFIER
• identifier=loginForm • identifier=password • identifier=continue • username
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - ID
• id=loginForm
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - NAME
• name=username • name=continue • name=continue value=Clear • name=continue Clear • name=continue type=button
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - XPATH
• xpath=/html/body/form[1] • //form[1] • xpath=//form[@id='loginForm'] • xpath=//form[input/@name='username']
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - XPATH
• //input[@name='username'] • //form[@id='loginForm']/input[1]
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - XPATH
• //input[@name='continue'][@type='button'] • //form[@id='loginForm']/input[4]
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - LINK
• link=Register
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - DOM
• dom=document.getElementById('loginForm') • dom=document.forms['loginForm'] • dom=document.forms[0]
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - DOM
• document.forms[0].username • document.forms[0].elements['username'] • document.forms[0].elements[0]
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - DOM
• document.forms[0].elements[3]
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - CSS
• css=form#loginForm
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - CSS
• css=input[name="username"] • css=input.req[type="text"]
<html> <body> <form id="loginForm"> <input class=“req” name="username" type="text"/> <input class="req pwd" name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - CSS
• css=input.pwd • css=#loginForm input:nth-child(2)
<html> <body> <form id="loginForm"> <input class="req" name="username" type="text"/> <input class="req pwd" name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
LOCATOR - CSS
• css=#loginForm input[type="button"]
<html> <body> <form id="loginForm"> <input name="username" type="text"/> <input name="password" type="password"/> <input name="continue" type="submit" value="Login"/> <input name="continue" type="button" value="Clear"/> </form> <a href="/pleaseSendMeSpam">Register</a> </body><html>
TEXT PATTERNS - GLOBBING• glob:
• *
• Match anything inside character class
• [ ]
• Character class
• [aeiou]
• [0-9]
• [a-zA-Z0-9]
TEXT PATTERNS – REGULAR EXPRESSIONS
• regexp: or regexpi:
PATTERN MATCH
. any single character
[ ] character class: any single character that appears inside the brackets
* quantifier: 0 or more of the preceding character (or group)
+ quantifier: 1 or more of the preceding character (or group)
? quantifier: 0 or 1 of the preceding character (or group)
{1,5} quantifier: 1 through 5 of the preceding character (or group)
| alternation: the character/group on the left or the character/group on the right
( ) grouping: often used with alternation and/or quantifier
TEXT PATTERNS - EXACT
• Exact:
• “Real *”
• glob:Real * will also match “Real number”
• exact:Real *
• regexp:Real \*
TEST SUITES• A test suite is a collection of tests• <html>
<head> <title>Test Suite Function Tests - Priority 1</title> </head> <body> <table> <tr><td><b>Suite Of Tests</b></td></tr> <tr><td><a href="./ultimateQuestionOfLive.html">Ultimate question of live</a></td></tr> <tr><td><a href="./recursion.html">Recursion</a></td></tr> </table> </body> </html>
COMMONLY USED COMMANDS
• open
• opens a page using a URL.
• click/clickAndWait
• performs a click operation, and optionally waits for a new page to load.
• waitForPageToLoad
• pauses execution until an expected new page loads. Called automatically when clickAndWait is used.
• waitForElementPresent
• pauses execution until an expected UI element, as defined by its HTML tag, is present on the page.
COMMONLY USED COMMANDS
• verifyTitle/assertTitle
• verifies an expected page title.
• verifyTextPresent
• verifies expected text is somewhere on the page.
• verifyElementPresent
• verifies an expected UI element, as defined by its HTML tag, is present on the page.
• verifyText
• verifies expected text and its corresponding HTML tag are present on the page.
ASSERTION OR VERIFICATION
• Assert
• Fail test, abort current test case
• Verify
• Fail test, continue to run the test case
TIP - BASEURL<tr> <td>store</td> <td>http://domain</td> <td>baseUrl</td> </tr> <! – … --><tr> <td>open</td> <td>${baseUrl}/page</td> <td></td> </tr>
TIP – OVERWRITE METHOD<tr> <td>getEval</td> <td>window._oldFooBar = window.fooBar; window.fooBar = function(arg1, arg2) { window._oldFooBar(arg1, arg2); window.fooBarData = { arg1: arg1, arg2: arg2 }; if (window.console){ window.console.log(window.fooBarData); } };</td> <td></td></tr>
TIP – NO ORPHANED TEXT<a href=“/property/123”>
Koekoekstraat 70 - Melle
<em>235.000 EUR</em></a>
<a href=“/property/123”> <span>Koekoekstraat 70 - Melle</span>
<em>235.000 EUR</em>
</a>
TIP – IDENTIFY FUNCTION<button id="login-button">
<span>Login</span>
</button>
WAI-ARIA role landmarks//li[@role="menuitem" and .=“About us ,”]
DOCKER TO THE RESCUE
• https://hub.docker.com/r/selenium/
• selenium/hub
• selenium/node-chrome
• selenium/node-firefox
DOCKER-COMPOSE
hub: image: selenium/hub ports: - "4444:4444"firefox: image: selenium/node-firefox links: - hubchrome: image: selenium/node-chrome links: - hub
EXAMPLEabstract class AbstractSeleniumTestCase extends TestCase { protected $webDriverUrl = ‘http://127.0.0.1:4444/wd/hub'; protected $webDriver; public function setUp() { $this->webDriver = RemoteWebDriver::create( $this->webDriverUrl, DesiredCapabilities::firefox() ); } public function tearDown() { if ($this->webDriver) { $this->webDriver->quit(); } }}
EXAMPLEpublic function testRecursion() { $this->webDriver->get('http://www.google.be'); $this->webDriver->findElement(WebDriverBy::id('lst-ib')) ->sendKeys('Recursion')->submit(); $this->webDriver->wait(10, 300) ->until( function ($webDriver) { try { $webDriver->findElement(WebDriverBy::cssSelector('a.spell')); return true; } catch (NoSuchElementException $ex) { return false; } } ); $aSpellElement = $this->webDriver->findElement(WebDriverBy::cssSelector('a.spell')); $this->assertEquals("Recursion", $aSpellElement->getText()); $aSpellElement->click(); $this->takeScreenshot(__FUNCTION__); }
RESOURCES• http://www.seleniumhq.org/
• https://github.com/becoded/talk-selenium-101
• https://github.com/facebook/php-webdriver
• http://magiumlib.com/