Improving Your Selenium WebDriver Tests - Belgium testing days_2016
-
Upload
roy-de-kleijn -
Category
Technology
-
view
203 -
download
0
Transcript of Improving Your Selenium WebDriver Tests - Belgium testing days_2016
![Page 1: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/1.jpg)
Improving Your Selenium WebDriver
Tests
Roy de KleijnTechnical Test ConsultantEmail: [email protected]: @TheWebTesterWebsite: http://www.rdekleijn.nlGithub: https://github.com/roydekleijn
![Page 2: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/2.jpg)
Question #1
What makes your Selenium WebDriver tests suck?
![Page 3: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/3.jpg)
Answer #1
Depending on third-party data
Synchronization issues
Cross-browser issues
Hard to locate elements
testdata
Slow feedback cycle
Flaky tests
High maintenance costs
![Page 4: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/4.jpg)
Lack of confidence
Results in …
![Page 5: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/5.jpg)
Contents• Introduction• Element locator tips & tricks• Implementing the Page Object Model• Utilize Data Objects• Handle synchronization• Speed-up and stabilize your tests (demo)• What we have learned
We will start with an actual Page Object Model implementation today
![Page 6: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/6.jpg)
Maintenance testM
aint
enan
ce e
ffort
Time
Start
with re
cord an
d playbac
k
Convert
recorded te
sts in
to code
Awesome, it
works
! Let’s
create
more UI te
sts Reality: code ends up into unmaintainable spaghetti
Design patt
erns applie
d
Implement fe
atures t
o mak
e tests
robust
wish
![Page 7: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/7.jpg)
Testing Pyramid
unit
UI
API
feed
back
-cyc
le
- Extremely fast- Smallest units of the application / isolates failure- Executed during build time- No dependency on data
- Extremely slow- Requires running application- Will change frequently- Dependency on data
- Fast- Covering boundary conditions- Start early in SD process - Requires running application- (some) dependency on data
![Page 8: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/8.jpg)
Mock External Interfaces
application
Interface 1
Interface 2
Interface 3
application
Interface 1
Interface 2
Interface 3m
ock
![Page 9: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/9.jpg)
Contents• Introduction• Element locator tips & tricks• Implementing the Page Object Model• Utilize Data Objects• Handle synchronization• Speed-up and stabilize your tests (demo)• What we have learned
We will start with an actual Page Object Model implementation today
![Page 10: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/10.jpg)
Question #2
What is wrong with these locators?
#1.//*[@id='wx-header-wrap']/div/div/div/div[2]/div[2]/div/section/div/form/input
#2.//*[@id='gnav-header-inner']/div/ul/li[2]/a
![Page 11: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/11.jpg)
Answer #2
They contain too much information about the location
![Page 12: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/12.jpg)
Closer look #1
![Page 13: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/13.jpg)
Closer look #1.//*[@id='wx-header-wrap']/div/div/div/div[2]/div[2]/div/section/div/form/input
What if the location of this element will change over time?
It can be written like this: input[class = ‘input--search’]Orinput.input—searchOrinput[name = ‘search’]
![Page 14: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/14.jpg)
Closer look #2
![Page 15: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/15.jpg)
Closer look #2.//*[@id='gnav-header-inner']/div/ul/li[2]/a
What if the order of the links will change over time ?
It can be written like this: a[id=register]Ora#register
![Page 16: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/16.jpg)
Attribute selectorscss xpath
Equals e[a=v] //e[@a=v]
Contains e[a*=v] //e[contains(@a, ‘v’)]
Starts-with e[a^=v] //e[starts-with(@a, ‘v’)]
Ends-with e[a$=v] //e[ends-with(@a, ‘v’)]
![Page 17: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/17.jpg)
AngularJS - elements
• Different way of locating elements• Binding• Model• Repeat
• ngWebDriver library (create by Paul Hammant)• https://github.com/paul-hammant/ngWebDriver• Logic from Protractor project
![Page 18: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/18.jpg)
• Enable debug info• Call angular.reloadWithDebugInfo(); in your browser debug console
• Execute the following snippet to reveal all the elements:
var bindings = document.getElementsByClassName('ng-binding');for (var i = 0; i < bindings.length; ++i) {var bindingName = angular.element(bindings[i]).data().$binding[0].exp ||angular.element(bindings[i]).data().$binding; console.log(bindingName.toString()); console.log(bindings[i]);}
![Page 19: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/19.jpg)
Contents• Introduction• Element locator tips & tricks• Implementing the Page Object Model• Utilize Data Objects• Handle synchronization• Speed-up and stabilize your tests (demo)• What we have learned
We will start with an actual Page Object Model implementation today
![Page 20: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/20.jpg)
Problems that arise
• Unmaintainable• Unreadable test scripts• Creation of test scripts is time consuming• Code duplication
![Page 21: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/21.jpg)
From problem to solution
![Page 22: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/22.jpg)
Solution
Each page contains only a part of the total functionality available on the website
Put page specific functionality in a class with a corresponding name
![Page 23: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/23.jpg)
Step-by-step plan
1. Identify necessary WebElements2. Create a class3. Define WebElements in corresponding classes4. Model the functionality of a page into methods5. Model the page flow by setting returntypes
![Page 24: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/24.jpg)
Identify necessary WebElements
![Page 25: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/25.jpg)
Create a class
A class with the name of the page extending from LoadableComponent
public class HomePage extends LoadableComponent<HomePage> { private WebDriver driver;
public HomePage(WebDriver driver) { this.driver = driver; PageFactory.initElements(driver, this); }
![Page 26: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/26.jpg)
Define WebElementsOn class level (above the methods)
@FindBy(css = "a.login")
private WebElement loginLink;
![Page 27: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/27.jpg)
Model the functionality
public LoginPage clickOnLoginLink() { loginLink.click(); return new LoginPage(driver); }
![Page 28: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/28.jpg)
Model the page flow
• Prerequisite:• Multiple pages are modelled
• Modify returntype• The returntype is the name of the page (class) where you are navigating
towards• Use the current class name, if you stay on the same page
![Page 29: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/29.jpg)
Model the page flow
public LoginPage clickOnLoginLink() { loginLink.click(); return new LoginPage(driver); }
Returning page
![Page 30: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/30.jpg)
Contents• Introduction• Element locator tips & tricks• Implementing the Page Object Model• Utilize Data Objects• Handle synchronization• Speed-up and stabilize your tests (demo)• What we have learned
We will start with an actual Page Object Model implementation today
![Page 31: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/31.jpg)
Data Objects final CustomerAccount account = new CustomerAccount.CustomerAccountBuilder("[email protected]","1qazxsw2").build();
Access data:account.getEmail()
account.getPassword()
![Page 32: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/32.jpg)
Data Objects - Complex final Order order = new Order.OrderBuilder()//
.withInvoiceAddress(new Address.AddressBuilder("abc street", "1234ab").build())// .withShippingAddress(new Address.AddressBuilder("shipstreet”, "4321ab").withCountry("The Netherlands").build())//
.build();
// Retrieve data from the objectSystem.out.println(order.getInvoiceAddress().getStreet());
System.out.println(order.getShippingAddress().getCountry());
![Page 33: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/33.jpg)
Contents• Introduction• Element locator tips & tricks• Implementing the Page Object Model• Utilize Data Objects• Handle synchronization• Speed-up and stabilize your tests (demo)• What we have learned
We will start with an actual Page Object Model implementation today
![Page 34: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/34.jpg)
Synchronization issues
• Browser has to start• Page has to load• AJAX request need to be finished• Or, loader should be gone before we can continue
![Page 35: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/35.jpg)
What NOT to do …
NEVER, use Thread.sleep();
• It will probably make your test unnecessary slow• You never know if you wait exactly long enough
![Page 36: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/36.jpg)
What to do…
• WebDriver build in wait mechanisms• implicitlyWait: poll till element is present• setScriptTimeout: time to wait for an asynchronous script to finish• pageLoadTimeout: time to wait for a page load to complete
• ngWebDriver• waitForAngularRequestsToFinish – wait for outstanding angular requests
• Custom (gist)• checkPendingRequests – wait for all HTTP requests to be finished
![Page 37: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/37.jpg)
Example 1
Wait for element to be clickable
@Testpublic void waitForElementToBeClickable() {
new WebDriverWait(driver, 20,100) //.until(ExpectedConditions.elementToBeClickable(
By.cssSelector("a.login")));}
![Page 38: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/38.jpg)
Example 2
Wait for loader to be invisible
@Testpublic void waitForElementNotToBeVisable() {
new WebDriverWait(driver, 20, 100) //.until(ExpectedConditions.invisibilityOfElementLocated(
By.cssSelector("loader")));}
![Page 39: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/39.jpg)
Contents• Introduction• Element locator tips & tricks• Implementing the Page Object Model• Utilize Data Objects• Handle synchronization• Speed-up and stabilize your tests (demo)• What we have learned
We will start with an actual Page Object Model implementation today
![Page 40: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/40.jpg)
Speed-up and stabilize your tests Windows 7
IEFF
Chrome
Windows vistaIEFF
UbuntuFF
Opera
Mac OSFF
ChromeOpera
…
Nodes
Hub
Specification
HUB
Test Scripts
![Page 41: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/41.jpg)
Docker Selenium
• Disposable Selenium Grid (in seconds)• Autoscaling features
• https://hub.docker.com/r/selenium/
![Page 42: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/42.jpg)
Docker-composeseleniumhub: image: selenium/hub ports: - 4444:4444firefoxnode: image: selenium/node-firefox environment: SCREEN_WIDTH: 2880 SCREEN_HEIGHT: 1800 ports: - 5900 links: - seleniumhub:hub
chromenode: image: selenium/node-chrome environment: SCREEN_WIDTH: 2880 SCREEN_HEIGHT: 1800 ports: - 5900 links: - seleniumhub:hub
![Page 43: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/43.jpg)
Docker commands
docker-compose up –d-d: Run containers in the background--force-recreate: Recreate containers entirely
Autoscaling:docker-compose scale firefoxnode=5 chromenode=1
![Page 44: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/44.jpg)
In practice
Implement or extend the Page Object Model
• Website• url: http://demo.technisch-testen.nl
• Source• Github: https://github.com/roydekleijn/webdriver-workshop
![Page 45: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/45.jpg)
Contents• Introduction• Element locator tips & tricks• Implementing the Page Object Model• Utilize Data Objects• Handle synchronization• Speed-up and stabilize your tests (demo)• What we have learned
We will start with an actual Page Object Model implementation today
![Page 46: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/46.jpg)
What we have learned today
Depending on third-party data
Cross-browser issues
Hard to locate elements
testdata
Slow feedback cycle
Flaky tests
High maintenance costs
Synchronization issuesAvoid Thread.sleep() or other hardcoded
waits
Utilize Page Object Model
id > name > css > xpath > angular
Mock interfaces
Run tests in parallel
Mock interfaces
Mock interfaces, setup clean environments,
implement page object model
![Page 47: Improving Your Selenium WebDriver Tests - Belgium testing days_2016](https://reader033.fdocuments.net/reader033/viewer/2022051123/5889cf0b1a28abca448b74bd/html5/thumbnails/47.jpg)
Thank you…
Roy de KleijnTechnical Test ConsultantEmail: [email protected]: @TheWebTesterWebsite: http://www.rdekleijn.nlGithub: https://github.com/roydekleijn