selenium 101

58

Upload: becoded

Post on 16-Apr-2017

284 views

Category:

Technology


0 download

TRANSCRIPT

SELENIUM 101automates browsers

I’M

• Bert Van Hauwaert

• CEO, CFO, CTO, … of be.coded

• Freelancer

NOTICEThis is a 101 talk!

(ANTI-)PATTERNS

ICE-CREAM CONE

Manual tests

AutomatedGUI testsIntegration

testsUnittests

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

BROWSER TESTING• Headless browser emulators

• Browser controllers

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

THE IDE

THE IDE

COMMANDS• Selenese

• 3 types

• Actions

• Accessors

• Assertions

SCRIPT SYNTAX• Command + 2 parameters

• Not always required

• Parameters

• Locator

• Text pattern to verify

• Text pattern or variable to insert

LOCATOR• Identifies an element

• identifier

• id

• name

• XPath

• link text

• DOM

• CSS

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

• Regular expressions

• Exact

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 CASE

• Set of Selenium commands

• Executed one by one

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 – OVERWRITE METHOD<tr>

<td>assertEval</td>

<td>window.fooBarData.arg1</td> <td>baz</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 ,”]

TIP – MAGNIUM• Magium = Selenium + Magento

DEMO• Answer to the Ultimate Question of Life, the

Universe, and Everything

• Recursion

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/

QUESTIONS ?