Post on 19-Mar-2018
Selenium WebDriver: Enhanced Integration with the
Java Stack
Notes
This is a training, NOT a presentation
Please be prepared to:
• Learn
• Ask questions
• Participate in the labs
http://tech.lds.org/wiki/Java_Stack_Training
Prerequisites
Required:
• "Unit Testing with TestNG"
• "Integration Testing and Test Data Builders"
Recommended:
• "Test Doubles, Mocks, and Matchers"
• "Functional Testing with the Java Stack Test Runner"
Agenda
• What is Selenium WebDriver?
• Using Stack Selenium
• Customizing Stack Selenium drivers and execution
• Using multiple drivers per test
• Selenium Grid
• Gotchas
SELENIUM WEBDRIVER?
What is
SELENIUM WEBDRIVER
http://www.flickr.com/photos/foto-kouba/6783399423/
SELENIUM WEBDRIVER
Browser Client
We
bD
rive
r
How To: WebDriver
• Add the Selenium WebDriver Maven dependencies
• Install the browser that you want to drive
• Write the code that:
• starts the driver
• executes the automation
• closes the driver
Maven Setup
Tests go in the QA module
• Tests should end in "FT"
Tests will be executed by the ALM module
project/ qa/ src/ test/ java/ pom.xml alm/ pom.xml pom.xml
Tests go here
Maven Setup
Tests go in the QA module
• Tests should end in "FT"
Tests will be executed by the ALM module
> mvn clean install > mvn alm-promote
Maven Setup
Tests go in the QA module
• Tests should end in "FT"
Tests will be executed by the ALM module
> mvn clean install > mvn alm-promote
How To: WebDriver public class BasicExampleFT {
@BeforeClass(alwaysRun = true) protected void setUp() { webDriver = new FirefoxDriver(); shortWait = new WebDriverWait(webDriver, 5); } @AfterClass(alwaysRun = true) protected void teardown() { webDriver.quit(); } @Test public void inSearchOfCheese() { webDriver.get("http://www.google.com"); WebElement element = webDriver.findElement(By.name("q")); element.sendKeys("cheese!"); element.submit(); shortWait.until(ExpectedConditions.titleIs("cheese!...")); }
}
org.lds.stack.training.webdriver.example.BasicExampleFT
Limitations
Setup and management of WebDriver
• When should I start the driver?
• When should I stop the driver?
• How do I configure the driver consistently?
Setup and management of browsers
• On workstation
• On server
STACK SELENIUM
Introducing
Goals
• Minimize effort to start, configure and manage tests
• Consistency in test structure and lifecycle
• Encourage good practices and habits
Stack Selenium
Leverages:
• TestNG
• Spring TestContext framework
STACK SELENIUM
Browser
Client
WebD
rive
r
WebD
river
Web
Driver
Browser
Getting Started
• Add the Selenium WebDriver Maven dependencies
• Install the browser that you want to drive
• Write the code that:
• starts the driver
• executes the automation
• closes the driver
Getting Started
• Add the Selenium WebDriver Maven dependencies
• Install the browser that you want to drive
• Write the code that:
• starts the driver
• executes the automation
• closes the driver
Add the stack-
selenium Maven
dependency
Maven Dependencies
<dependency> <groupId>org.lds.stack.qa</groupId> <artifactId>stack-selenium</artifactId>
</dependency> <dependency>
<groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-firefox-driver</artifactId>
</dependency>
Latest version of
stack-selenium is
4.2.2.
Getting Started
public class ImprovedExampleFT extends AbstractDefaultSeleniumFT {
@Test public void inSearchOfCheese() {
webDriver.get("http://www.google.com"); WebElement element = webDriver.findElement(By.name("q")); element.sendKeys("cheese!"); element.submit(); shortWait.until(ExpectedConditions.titleIs("cheese…"));
} }
org.lds.stack.training.webdriver.example.ImprovedExampleFT
What's Provided?
WebDriver reference (webDriver)
WebDriverWait objects ("waiters")
• shortWait (5 seconds)
• mediumWait (10 seconds)
• longWait (30 seconds)
LAB 1
http://openclipart.org/detail/22736/lab-icon-2-by-papapishu
DRIVER SELECTION AND MANAGEMENT
Customizing
Framework Configuration
Uses Spring configuration classes
• Configuration class
• On test class
@Configuration // other annotations, as needed public class MyConfiguration { // one or more bean definitions here }
@ContextConfiguration(classes = MyConfiguration.class) public class MyFunctionalTestFT extends AbstractSeleniumFT { // tests go here }
Framework Configuration
Uses Spring configuration classes
• Configuration class
• On test class
@Configuration // other annotations, as needed public class MyConfiguration { // one or more bean definitions here }
@ContextConfiguration(classes = MyConfiguration.class) public class MyFunctionalTestFT extends AbstractSeleniumFT { // tests go here }
Which Class Should I
Use? AbstractDefaultSeleniumFT
• "The defaults drivers and waits work for me"
AbstractSeleniumFT
• "I want more control over my drivers and waits"
AbstractMultiDriverSeleniumFT
• "I want to run the same tests over multiple drivers"
(and I like really long class names)
Framework Configuration
• Add our own configuration annotations to configuration class
@ContextConfiguration( classes = AbstractDefaultSeleniumFT.DefaultConfiguration.class) public class AbstractDefaultSeleniumFT extends AbstractSeleniumFT { // various injected elements @Configuration @EnableSeleniumSupport(includeDefaultDrivers = true) @DefaultWebDriverWaits static class DefaultConfiguration { } }
org.lds.stack.qa.selenium.AbstractDefaultSeleniumFT
@EnableSeleniumSupport
USE ON: Spring configuration classes
Makes the switchable/configurable web driver available
• Registers any web driver configurations
Attributes:
• includeDefaultDrivers (default false): include default drivers in the
configuration
@Configuration @EnableSeleniumSupport class MyConfiguration { }
includeDefaultDrivers=true
Adds the following drivers to the test container:
• DEFAULT-htmlUnit.HTML_UNIT
• DEFAULT-firefox.FIREFOX
• DEFAULT-chrome.CHROME
@Configuration @EnableSeleniumSupport(includeDefaultDrivers = true) class MyConfiguration { }
includeDefaultDrivers=true
Adds the following drivers to the test container:
• DEFAULT-htmlUnit.HTML_UNIT
• DEFAULT-firefox.FIREFOX
• DEFAULT-chrome.CHROME
Only the drivers found
in dependencies
@Configuration @EnableSeleniumSupport(includeDefaultDrivers = true) class MyConfiguration { }
DRIVER IDENTIFIERS
A brief detour
Driver Identifiers
DEFAULT-htmlUnit.HTML_UNIT
Driver key or name Driver Type
Driver Identifiers
DEFAULT-htmlUnit.HTML_UNIT
Driver key or name Driver Type
You decide on
a name! Must be a valid
value
Which Driver to Use
• REMOTE
• HTML_UNIT
• FIREFOX
• CHROME
Then by driver
name/key in
alphabetical order
org.lds.stack.qa.selenium.core.DriverType
Quiz #1
• DEFAULT-chrome.CHROME
• DEFAULT-firefox.FIREFOX
• DEFAULT-htmlUnit.HTML_UNIT
Quiz #1
• DEFAULT-chrome.CHROME
• DEFAULT-firefox.FIREFOX
• DEFAULT-htmlUnit.HTML_UNIT X
Quiz #2
• driver1.CHROME
• driver1.REMOTE
• driver2.CHROME
Quiz #2
• driver1.CHROME
• driver1.REMOTE X
• driver2.CHROME
BACK TO OUR PROGRAM
And now…
@UseSeleniumDriver
USE ON: test classes and test methods
Specifies which driver to use for a class or method
Attributes:
• key (optional): the driver name or key or use
• driverType (optional): the driver type to use
@UseSeleniumDriver( key = "myDriver", driverType = DriverType.HTML_UNIT) @ContextConfiguration(classes = MyConfiguration.class) public class MyTestFT extends AbstractSeleniumFT { // code happens }
org.lds.stack.training.webdriver.example.UseSeleniumDriverFT
@UseSeleniumDriver
USE ON: test classes and test methods
Specifies which driver to use for a class or method
Attributes:
• key (optional): the driver name or key or use
• driverType (optional): the driver type to use
@UseSeleniumDriver( key = "myDriver", driverType = DriverType.HTML_UNIT) @Test public void testSomethingOnlyWithThisDriver() { // test something }
org.lds.stack.training.webdriver.example.UseSeleniumDriverFT
@DriverClose
USE ON: test classes and test methods
Manages when a WebDriver should be closed
Attributes:
• closeAround (defaults to CLASS): when should driver be closed
@DriverClose @ContextConfiguration(classes = MyConfiguration.class) public class MyTestFT extends AbstractSeleniumFT { // code happens }
org.lds.stack.training.webdriver.example.DriverCloseFT
@DriverClose
USE ON: test classes and test methods
Manages when a WebDriver should be closed
Attributes:
• closeAround (defaults to CLASS): when should driver be closed
@DriverClose(closeAround = DriverClose.CloseAround.METHODS) @ContextConfiguration(classes = MyConfiguration.class) public class MyTestFT extends AbstractSeleniumFT { // code happens }
org.lds.stack.training.webdriver.example.DriverCloseFT
@DriverClose
USE ON: test classes and test methods
Manages when a WebDriver should be closed
Attributes:
• closeAround (defaults to CLASS): when should driver be closed
@DriverClose @Test public void testSomethingOnlyWithThisDriver() { // test something }
org.lds.stack.training.webdriver.example.DriverCloseFT
@DefaultWebDriverWaits
USE ON: Spring configuration classes
Adds the following WebDriverWait objects:
• shortWait (5 seconds)
• mediumWait (10 seconds)
• longWait (30 seconds)
@Configuration @DefaultWebDriverWaits class MyConfiguration { }
org.lds.stack.training.webdriver.example.DefaultWebDriverWaitsFT
@WebDriverWait
USE ON: Spring configuration classes
Adds a WebDriverWait with the specified name
Attributes
• name: name of the waiter
• timeout: time (in seconds) that waiter should wait
• interval (defaults to 250): frequency waiter should poll (in ms)
@Configuration @WebDriverWait(name = "myWait" timeout = 7) class MyConfiguration { }
org.lds.stack.training.webdriver.example.WebDriverWaitFT
@WebDriverWaits
USE ON: Spring configuration classes
Specifies a collection of @WebDriverWait elements
Attributes
• value: zero or more @WebDriverWait elements
@Configuration @WebDriverWaits({ @WebDriverWait(name = "shortWait", timeout = 5), @WebDriverWait(name = "mediumWait", timeout = 10), @WebDriverWait(name = "longWait", timeout = 30) }) class MyConfiguration { }
org.lds.stack.training.webdriver.example.WebDriverWaitsFT
Annotation Summary
Spring Configuration
• @EnableSeleniumSupport
• @DefaultWebDriverWaits
• @WebDriverWait
• @WebDriverWaits
Test Configuration
• @UseSeleniumDriver
• @DriverClose
• @UseSeleniumDrivers
…to be
continued
WebDriverConfigurer
USE IN: Spring configuration classes
Defines a new WebDriver for use in tests
@Configuration class MyConfiguration { @Bean(name = "myHtmlUnit-driver") public WebDriverConfigurer<HtmlUnitDriver> htmlUnitDriver() { return new WebDriverConfigurer<HtmlUnitDriver>() { public HtmlUnitDriver configure() { return new HtmlUnitDriver(); } }; }
org.lds.stack.training.webdriver.example.WebDriverConfigurerFT
WebDriverConfigurer
USE IN: Spring configuration classes
Defines a new WebDriver for use in tests
@Configuration class MyConfiguration { @Bean(name = "myHtmlUnit-driver") public WebDriverConfigurer<HtmlUnitDriver> htmlUnitDriver() { return new WebDriverConfigurer<HtmlUnitDriver>() { public HtmlUnitDriver configure() { return new HtmlUnitDriver(); } }; }
If omitted, uses the
method name for the
driver name
org.lds.stack.training.webdriver.example.WebDriverConfigurerFT
LAB 2
http://openclipart.org/detail/22736/lab-icon-2-by-papapishu
MULTIPLE DRIVERS ON TESTS
Using
Using Multiple Drivers
Options include:
• Duplicate test methods or classes
• Create TestNG suite configurations
Using Multiple Drivers
Options include:
• Duplicate test methods or classes
• Create TestNG suite configurations
• Use AbstractMultiDriverSeleniumFT!
Multiple Drivers - Steps
• Extend AbstractMultiDriverSeleniumFT
• Create a Spring configuration class
• Attach configuration class to test
• Add @UseSeleniumDrivers annotation to class
• Add constructor to accept driver selectors
Using Multiple Drivers
@UseSeleniumDrivers(drivers = { @UseSeleniumDriver(driverType = DriverType.HTML_UNIT), @UseSeleniumDriver(driverType = DriverType.FIREFOX) })
@ContextConfiguration(classes = MultiDriverConfiguration.class) public class MultiDriverSeleniumFT
extends AbstractMultiDriverSeleniumFT { @Autowired private Wait<WebDriver> shortWait; @Factory(dataProvider = "driverDataProvider") public MultiDriverSeleniumFT(String predicateAsString) {
super(predicateAsString); } // some tests
}
org.lds.stack.training.webdriver.example.MultiDriverSeleniumFT
SELENIUM GRID
Using
SELENIUM GRID
Browser Client
We
bD
rive
r
Selenium Grid – Getting
Started • Create a RemoteWebDriver configuration for each browser
• Select the driver using @UseSeleniumDriver
@Bean public WebDriverConfigurer<RemoteWebDriver> chromeGrid() {
return new WebDriverConfigurer<RemoteWebDriver>() { public RemoteWebDriver configure() {
return new RemoteWebDriver( new URL(GRID_ROOT_URL + "/wd/hub"), DesiredCapabilities.chrome());
} };
}
org.lds.stack.training.webdriver.example.GridExampleFT
HEADLESS DRIVER?
http://www.flickr.com/photos/friedwater/2750747024/
GOTCHAS
http://www.flickr.com/photos/kwl/5199093132/
Updating Versions
• Stack-selenium version
• Selenium version
<properties> ... <stackSeleniumVersion>4.2.2</stackSeleniumVersion> ...
</properties>
<properties> ... <seleniumVersion>2.30.0</seleniumVersion> ...
</properties>
Configuring Browsers
Read the docs!
• Selenium WebDriver site –
https://code.google.com/p/selenium/
• ChromeDriver –
https://code.google.com/p/selenium/wiki/ChromeDriver
• FirefoxDriver –
https://code.google.com/p/selenium/wiki/FirefoxDriver
SUMMARY
Upcoming Features
Support for augmenters
• TakesScreenshot
• JavaScriptExecutor
Increased driver support
• GhostDriver
• SafariDriver
More WebDriver expectations
Stack Selenium, Part Two
• WebDriver testing techniques
• Page Objects
• Environment configuration
Java Testing Toolkit
• Testing framework: TestNG
• Test assertions: Hamcrest Matchers and Stack Unit Test utilities
• Test doubles and mocks: Mockito
• Integration testing framework: Spring TestContext
• Test data builders: Make-it-Easy
• Test runner: Stack TestRunner
• Functional testing: Stack Selenium
THANKS