SlideShare a Scribd company logo
1 
Automation Abstractions: 
Page Objects and Beyond 
Alan Richardson 
@eviltester 
https://xp-dev.com/svn/AutomationAbstractions 
www.SeleniumSimplified.com 
www.EvilTester.com 
www.CompendiumDev.co.uk 
www.JavaForTesters.com
2 
What is Abstraction? 
● Modelling 
● Separation of concerns 
● Logical vs Physical 
● Functional vs Structural 
● Interfaces vs Implementations 
● Data / Entities / Persistence 
● Functionality / Task Flow 
● Goals / Strategies 
● Layers – GUI, DB, HTTP 
● Etc.
“I must create a system. or be 
enslav'd by another Mans; I 
will not reason & compare: 
my business is to create” 
William Blake, 1820 
Jerusalem: The Emanation of the Giant Albion 
3 
http://www.blakearchive.org/exist/blake/archive/object.xq?objectid=jerusalem.e.illbk.10&java=no
https://xp-dev.com/svn/AutomationAbstractions 
4 
Example Test Without 
Abstraction 
@Before 
public void startDriver(){ 
@Test 
public void canCreateAToDoWithNoAbstraction(){ 
driver.get("http://todomvc.com/architecture-examples/backbone/"); 
int originalNumberOfTodos = driver.findElements( 
By.cssSelector("ul#todo-list li")).size(); 
WebElement createTodo = driver.findElement(By.id("new-todo")); 
createTodo.click(); 
createTodo.sendKeys("new task"); 
createTodo.sendKeys(Keys.ENTER); 
assertThat(driver.findElement( 
By.id("filters")).isDisplayed(), is(true)); 
int newToDos = driver.findElements( 
By.cssSelector("ul#todo-list li")).size(); 
assertThat(newToDos, greaterThan(originalNumberOfTodos)); 
} 
driver = new FirefoxDriver(); 
} 
@After 
public void stopDriver(){ 
driver.close(); 
driver.quit(); 
} 
NoAbstractionTest.java
But this does use some 
abstraction layers 
LLooccaattoorr A Abbssttrraaccttioionns 
WebElement Generic Element Abstraction 
5 
Example Test Without 
Abstraction 
@Before 
public void startDriver(){ 
WebDriver Generic Browser Abstraction 
@Test 
public void canCreateAToDoWithNoAbstraction(){ 
Firefox Browser Abstraction 
driver.get("http://todomvc.com/architecture-examples/backbone/"); 
int originalNumberOfTodos = driver.findElements( 
By.cssSelector("ul#todo-list li")).size(); 
WebElement createTodo = driver.findElement(By.id("new-todo")); 
createTodo.click(); 
createTodo.sendKeys("new task"); 
createTodo.sendKeys(Keys.ENTER); 
assertThat(driver.findElement( 
By.id("filters")).isDisplayed(), is(true)); 
int newToDos = driver.findElements( 
Manipulation Abstractions 
By.cssSelector("ul#todo-list li")).size(); 
assertThat(newToDos, greaterThan(originalNumberOfTodos)); 
} 
driver = new FirefoxDriver(); 
} 
@After 
public void stopDriver(){ 
driver.close(); 
driver.quit(); 
} 
NoAbstractionTest.java
6 
WebDriver provides abstractions 
● Browser 
● DOM 
● Web Element 
Tool vendors gain value from generic abstractions. 
You gain value from 'domain' abstractions.
7 
Example Test With Abstraction 
@Before 
public void startDriver(){ 
@Test 
public void canCreateAToDoWithAbstraction(){ 
TodoMVCUser user = 
new TodoMVCUser(driver, new TodoMVCSite()); 
user.opensApplication().and().createNewToDo("new task"); 
ApplicationPageFunctional page = 
new ApplicationPageFunctional(driver, 
new TodoMVCSite()); 
assertThat(page.getCountOfTodoDoItems(), is(1)); 
assertThat(page.isFooterVisible(), is(true)); 
} 
driver = new FirefoxDriver(); 
} 
@After 
public void stopDriver(){ 
driver.close(); 
driver.quit(); 
} 
NoAbstractionTest.java
8 
Why Abstraction? 
● Change implementations 
● Single Responsibility – only changes when 
necessary 
● Makes automation readable and maintainable 
● We can unit test some of our test code 
● etc. 
https://xp-dev.com/svn/AutomationAbstractions
9 
Some Abstraction Layer Categories 
1) Data 
– Generic Data Abstractions e.g. email, postcode 
2) Physical 
– Physical layout of your application e.g. pages, 
components 
– Navigation across pages 
3) Domain 
– Your application Entities domain e.g. user, account 
4) Logical 
– User actions, workflows
10 
Common Automation Abstractions 
● Page Objects: pages, components, widgets 
● Dom Element Abstractions: select, textbox, etc. 
● Domain Objects: user, account, order 
● Gherkin (Given/When/And/Then) 
● Domain Specific Languages: code, keywords 
● ... 
https://xp-dev.com/svn/AutomationAbstractions
11 
Abstraction != Implementation 
● Abstraction != Tool / Framework / 
Implementation 
● Gherkin != Cucumber 
● Page Object != Page Factory / Slow Loadable 
● DSL != Keyword Driven 
If we want to get good at abstraction then we 
need to model, split apart, make the relationships 
clear, and be aware of our options.
12 
Page Objects 
● The most obvious 
automation abstraction 
● What is it? 
– A page? A Component? 
● Do web applications still 
have pages?
A Page Object that abstracts a Page 
13 
● Often has methods for 
– Opening the page 
– Accessing elements 
– Doing stuff, and navigating as a side-effect 
– Logical high level functionality e.g. login 
– Low level physical functionality e.g. 
typeUsername, clickLoginButton 
Should a Page Object be responsible for all of 
this?
14 
Page Object Design Decisions 
● What methods does it have? 
– Functional 
● login(username, password), 
● loginAs(user) 
– Structural 
● enterName(username), enterPassword(password), 
clickLogin(), submitLoginForm(username, password) 
● Does it expose elements or not? 
– public WebElement loginButton; 
– public WebElement getLoginButton(); 
– public clickLoginButton();
15 
Page Object Functionality 
Approaches 
● Expose WebElements Directly 
– Leads to WebElement Abstractions 
– public TextField userNameField; 
● Hide WebElements behind physical functional 
methods e.g. typeUserName("bob"); 
● Logical helper methods e.g. 
loginAs(name,pass) 
● Layers of Page Objects 
– Physical 
– Logical
16 
Navigation Design Decisions 
● Does a Page Object return other pages? 
public IssueListPage submit(){ 
driver.findElement(By.id(“submit”)).click(); 
return new IssueListPage(driver); 
} 
● Or Navigate implicitly after interactions 
● Or have navigation objects
17 
Implicit or Explicit Wait? 
● Implicit Wait 
driver.manage().timeouts(). 
implicitlyWait(15L, TimeUnit.SECONDS); 
assertThat(driver.findElement( 
By.id("filters")).isDisplayed() 
, is(true)); 
● Explicit Wait 
driver.manage().timeouts(). 
implicitlyWait(0L, TimeUnit.SECONDS); 
WebDriverWait wait = new WebDriverWait(driver,15); 
wait.until(ExpectedConditions.elementToBeClickable 
(By.id("filters"))); 
Example: 'NoAbstractionTest.java'
18 
Implementing Page Objects 
● POJO 
– Plain object, driver in constructor, methods use 
driver.<method> 
● Page Factory 
– Annotated elements, lazy instantiation via reflection 
● LoadableComponent 
– Common interface (load, isLoaded), isLoaded 
throws Error 
● SlowLoadableComponent 
– Common interface, waits for on isLoaded 
● Other approaches?
19 
Example Implementations 
https://xp-dev.com/svn/AutomationAbstractions
20 
POJO 
● 'ApplicationPage.java' 
– Used in 'SequentialCreationOfTest.java' 
– Not much refactoring in the example 
● Simple Class 
● WebDriver passed to constructor 
● Composition of any components 
● e.g. 
– com.seleniumsimplified.todomvc.page.pojo 
– 'ApplicationPage.java' 
● Not much refactoring in the example
Pojo Example 
21
22 
Functional vs Structural 
● Functional 
– loginAs(username, password) 
● Structural 
– enterUsername 
– enterPassword 
– clickLoginButton 
– submitLoginForm(username, password)
23 
Functional Vs Structural Example 
● One way of answering “what methods to put on 
a page object” 
– Is it functional / behavioural? 
– Is it structural / Physical? 
● Functional 'uses' Structural implementation 
● Why? 
– Sometimes it is just a naming difference 
– Handling exceptions in functional but not structural 
– Higher level methods in Functional 
– Different concepts e.g. deleteLastItem
24 
Page Factory 
● Annotate fields with @FindBy 
● Instantiate in constructor using 
PageFactory.initElements 
– Can create your own page factory initialiser 
● Avoids boilerplate accessor methods 
● Fast to create Page Objects 
● Might become harder to expand and maintain
25 
Page Factory Example 
@FindBy(how = How.CSS, using="#todo-count strong") 
private WebElement countElementStrong; 
@FindBy(how = How.CSS, using="#todo-count") 
private WebElement countElement; 
@FindBy(how = How.CSS, using="#filters li a") 
List<WebElement> filters; 
@FindBy(how = How.ID, using="clear-completed") 
List<WebElement> clearCompletedAsList; 
@FindBy(how = How.ID, using="clear-completed") 
WebElement clearCompletedButton; 
public ApplicationPageStructuralFactory(WebDriver driver, TodoMVCSite todoMVCSite) 
{ 
PageFactory.initElements(driver, this); 
this.driver = driver; 
...
26 
SlowLoadableComponent 
● Some pages and components need 
synchronisation to wait till they are ready 
– One approach – SlowLoadableComponent adds 
responsibility for waiting, to the page 
● extend SlowLoadableComponent 
● Standard interface for synchronisation on load 
– get() 
● If isLoaded then return this Else load 
● While not loaded{ wait for 200 millseconds} 
– Implement load and isLoaded
27 
Fluent Page Objects 
todoMVC = new ApplicationPageFunctionalFluent( 
driver, todoMVCSite); 
todoMVC.get(); 
todoMVC.enterNewToDo("First Completed Item"). 
and(). 
toggleCompletionOfLastItem(). 
then(). 
enterNewToDo("Still to do this"). 
and(). 
enterNewToDo("Still to do this too"). 
then(). 
filterOnCompleted();
28 
Fluent Page Objects 
● Methods return the page object or other objects 
instead of void 
– void clickDeleteButton(); 
– PageObject clickDeleteButton(); 
● Syntactic sugar methods: 
– and(), then(), also() 
● Can work well at high levels of abstraction and 
when no navigation involved 
● Train Wreck?
Navigation Options 
29 
● Direct in Test: page.get(); page.waitFor(); 
● Instantiate new pages based on test flow 
– Navigation as side-effect, may have to bypass 'get' 
– Loadable pages, non-loadable, support classes 
● Page Object methods might return other Pages 
– e.g. a method on the login page might be 
● MyAccountPage clickLogin(); 
● We might use navigation objects 
– direct, Jump.to(MyAccountPage.class) 
– path based (current page → desired page) 
● Navigate.to(MyAccountPage.class)
30 
Possible Domain Abstractions 
● Logical Objects 
– ToDo 
– ToDoList 
● Physical Objects 
– LocallyStoredToDo 
● Actors 
– User 
● Environment 
– Site 
– Implementation
31 
Page Objects & Domain Objects 
● Instead of 
– todoMVC.enterNewToDo(“New Item”) 
● We could have have 
– ToDoItem newItem = new ToDoItem(“New Item”); 
– todoMVC.enterNewToDo(newItem); 
● See code in DomainBasedTest
32 
Domain Objects That Span Logical 
& Physical 
e.g. User 
● user.createNewToDo(“new item”) 
● user.createNewToDo(newItem) 
● See use in NoAbstractionTest
33 
Sometimes it is possible to over 
think this stuff 
● Don't let thinking about this slow you down 
● Conduct experiments 
● Refactor 
● Rethink if 
– you are maintaining too much 
– your abstraction layer stops you doing stuff 
– you are 'working around' your abstraction layers
34 
Element 
Abstractions
35 
Element Abstraction Example 
public interface Checkbox { 
public boolean isChecked(); 
public Checkbox check(); 
public Checkbox uncheck(); 
public Checkbox toggle(); 
} 
● Would you include 'toggle'? 
https://xp-dev.com/svn/AutomationAbstractions
36 
Element Abstractions 
● Existing support classes: Select, 
● Possible: TextBox, Checkbox, TextBox, File etc. 
● Can enforce Semantics 
– Checkbox: isChecked, check(), uncheck(), toggle() 
– TextBox: clear(), enterText() 
– etc. 
● Pass back from Page Objects into test?
Element Abstraction Pros and Cons 
37 
● May have to create a custom page factory 
● Can help 'restrict' code i.e. check or uncheck, 
rather than click, enforces 'semantics' 
● If you create them... 
– allow return WebElement 
● so that I can go beyond the abstraction layer if I need to. 
Not required if it is just a WebElement wrapper. 
https://xp-dev.com/svn/AutomationAbstractions
38 
Component Abstractions 
● Shared Components/Widgets on the page 
● e.g. 
– VisibleToDoEntry, VisibleToDoList 
– Filters, Footer, Header, etc. 
● Could have 'functional' representation for 
repeated items e.g. login forms 
● Could have 'structural' representation 
● Likely use : page object composition
39 
Component Abstraction Example 
TodoEntry todo = page.getToDoEntryAt(lastItemPosition); 
todo.markCompleted(); 
Instead of 
page.markTodoCompleted(lastItemPosition);
40 
Gherkin as an abstraction layer 
Feature: We can create and edit To Do lists in ToDoMvc 
We want to amend todos in ToDoMVC because that is 
the set of exercises on the abstraction tutorial 
Scenario: Create a ToDo Item 
Given a user opens a blank ToDoMVC page 
When the user creates a todo "new task" 
Then they see 1 todo item on the page 
● Implement steps using highest appropriate 
abstraction layer 
● CucumberJVM as 'DSL implementor' 
● 'Expressibility' vs 'Step Re-use' 
● See todomvc.feature and ToDoMvcSteps
41 
My modeling biases 
● Driver 
– Inject so instantiate any page or component as 
required/desired at any time 
● Explicit Synchronisation 
– To make sure that the desired object is available 
and ready for use (as defined by synchronisation) 
● Navigation 
– Implicit (via taking action e.g. click) 
– Explicit Navigation Object, not in page object 
● Open/jump (via driver.get) 
● To (state model from current, to desired)
42 
My modeling biases 
● Page Objects 
– Physical 
● abstract the 'real world' 
– Components 
● For common features on the page 
– Logical 
● abstract the functionality 
● Sometimes these are entity methods not page objects 
– e.g. user.registers().and().logsin() 
● I tend not to.... 
– abstract WebElements
43 
My modeling biases 
● I tend not to.... 
– abstract WebElements 
– Use inheritence to create a model of the app 
● e.g. MyAppPage extends GenericAppPage 
– Use 3rd party abstractions on top of WebDriver
44 
Are there rights and wrongs? 
● Right / Wrong? 
● Decisions? 
● Project/Team/Organisation Standards? 
Identify your own biases - 
Experiment 
Recognise your decisions
45 
Decisions 
● The 'limits' and overlap of Abstraction Layers 
● Build it now, or 'refactor to' later 
● How much change is anticipated? 
– To which layer? GUI, Business domain, Workflow? 
● Who is working with the automation code? 
– Skill levels? Support needed? 
● How/When with the automation execute?
46 
Other Useful Links 
● Jeff “Cheezy” Morgan – page-object ruby gem, 
data_magic gem and stareast code 
– https://github.com/cheezy?tab=repositories 
● Marcus Merrell 
– Self-Generating Test Artifacts for Selenium/WebDriver 
– https://www.youtube.com/watch?v=mSCFsUOgPpw 
● Anand Ramdeo 
– One Step at a Time 
– https://www.youtube.com/watch?v=dFPgzH_XP1I 
https://xp-dev.com/svn/AutomationAbstractions
47 
Homework 
● Using the code at 
https://xp-dev.com/svn/AutomationAbstractions/ 
– Compare the different implementations under 'main' 
● com.seleniumsimplified.todomvc.page 
– Investigate how the Page Objects delegate to each 
other, and the Domain Objects use Page Objects 
– Examine the 'test' usage of the Page Objects and 
Domain Objects 
– Examine the different navigation approaches
48 
Blogs and Websites 
● CompendiumDev.co.uk 
● SeleniumSimplified.com 
● EvilTester.com 
● JavaForTesters.com 
● Twitter: @eviltester 
Online Training Courses 
● Technical Web Testing 101 
Unow.be/at/techwebtest101 
● Intro to Selenium 
Unow.be/at/startwebdriver 
● Selenium 2 WebDriver API 
Unow.be/at/webdriverapi 
Videos 
youtube.com/user/EviltesterVideos 
Books 
Selenium Simplified 
Unow.be/rc/selsimp 
Java For Testers 
leanpub.com/javaForTesters 
Alan Richardson 
uk.linkedin.com/in/eviltester 
Independent Test Consultant 
& Custom Training 
Contact Alan 
http://compendiumdev.co.uk/contact

More Related Content

What's hot (20)

PPTX
Spring boot
sdeeg
 
PDF
An Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
shaunthomas999
 
PDF
Perils of Page-Object Pattern
Anand Bagmar
 
PDF
jQuery Effects
Adelon Zeta
 
PPTX
Selenium introduction
Pankaj Dubey
 
PDF
Apache Server Tutorial
Jagat Kothari
 
PPT
Introduction to Drools
giurca
 
PPT
Page object with selenide
COMAQA.BY
 
PPTX
Cracking the Coding interview (Abbreviated) - aug 2016
Gayle McDowell
 
PPTX
Webpack Introduction
Anjali Chawla
 
PDF
Don't Be Mocked by your Mocks - Best Practices using Mocks
Victor Rentea
 
PDF
HandsOn ProxySQL Tutorial - PLSC18
Derek Downey
 
PDF
Clean coding-practices
John Ferguson Smart Limited
 
PDF
How to set up orchestrator to manage thousands of MySQL servers
Simon J Mudd
 
PPTX
Clean Code - The Next Chapter
Victor Rentea
 
ODP
Introduction to jQuery
manugoel2003
 
PPTX
Nextjs13.pptx
DivyanshGupta922023
 
PPTX
Clean code
Henrique Smoco
 
PDF
Spring Boot
Pei-Tang Huang
 
PDF
Unit testing, principles
Renato Primavera
 
Spring boot
sdeeg
 
An Introduction to JUnit 5 and how to use it with Spring boot tests and Mockito
shaunthomas999
 
Perils of Page-Object Pattern
Anand Bagmar
 
jQuery Effects
Adelon Zeta
 
Selenium introduction
Pankaj Dubey
 
Apache Server Tutorial
Jagat Kothari
 
Introduction to Drools
giurca
 
Page object with selenide
COMAQA.BY
 
Cracking the Coding interview (Abbreviated) - aug 2016
Gayle McDowell
 
Webpack Introduction
Anjali Chawla
 
Don't Be Mocked by your Mocks - Best Practices using Mocks
Victor Rentea
 
HandsOn ProxySQL Tutorial - PLSC18
Derek Downey
 
Clean coding-practices
John Ferguson Smart Limited
 
How to set up orchestrator to manage thousands of MySQL servers
Simon J Mudd
 
Clean Code - The Next Chapter
Victor Rentea
 
Introduction to jQuery
manugoel2003
 
Nextjs13.pptx
DivyanshGupta922023
 
Clean code
Henrique Smoco
 
Spring Boot
Pei-Tang Huang
 
Unit testing, principles
Renato Primavera
 

Viewers also liked (20)

PDF
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...
Alan Richardson
 
PDF
Using The Page Object Pattern
Dante Briones
 
PDF
Page Objects Done Right - selenium conference 2014
Oren Rubin
 
PDF
Beyond Page Objects
Dante Briones
 
PDF
Better Page Object Handling with Loadable Component Pattern
Sargis Sargsyan
 
PDF
Unbearable Test Code Smell
Steven Mak
 
PDF
Abstraction Layers Test Management Summit Faciliated Session 2014
Alan Richardson
 
PDF
Applying Innovation at different levels of abstraction
Jathish MJ
 
PPT
Innovative Test Automation Solution
Alan Lee White
 
PDF
Lessons learned with Bdd: a tutorial
Alan Richardson
 
PPT
Ch1 1
Sumant Diwakar
 
PDF
Is Abstraction the Key to Artificial Intelligence? - Lorenza Saitta
WithTheBest
 
PDF
Practical Test Automation Deep Dive
Alan Richardson
 
PDF
Test Automation Day 2015 Keynote Alan Richardson - Practical Lessons Learned ...
Alan Richardson
 
PPTX
Multithreading Design Patterns
PostSharp Technologies
 
PDF
Evil testers guide to technical testing
Alan Richardson
 
PDF
Lessons Learned When Automating
Alan Richardson
 
PPT
20041221 gui testing survey
Will Shen
 
PDF
Why Test Automation Fails
Ranorex
 
PDF
Automated Test Case Generation and Execution from Models
Dharmalingam Ganesan
 
Hands on Exploration of Page Objects and Abstraction Layers with Selenium Web...
Alan Richardson
 
Using The Page Object Pattern
Dante Briones
 
Page Objects Done Right - selenium conference 2014
Oren Rubin
 
Beyond Page Objects
Dante Briones
 
Better Page Object Handling with Loadable Component Pattern
Sargis Sargsyan
 
Unbearable Test Code Smell
Steven Mak
 
Abstraction Layers Test Management Summit Faciliated Session 2014
Alan Richardson
 
Applying Innovation at different levels of abstraction
Jathish MJ
 
Innovative Test Automation Solution
Alan Lee White
 
Lessons learned with Bdd: a tutorial
Alan Richardson
 
Is Abstraction the Key to Artificial Intelligence? - Lorenza Saitta
WithTheBest
 
Practical Test Automation Deep Dive
Alan Richardson
 
Test Automation Day 2015 Keynote Alan Richardson - Practical Lessons Learned ...
Alan Richardson
 
Multithreading Design Patterns
PostSharp Technologies
 
Evil testers guide to technical testing
Alan Richardson
 
Lessons Learned When Automating
Alan Richardson
 
20041221 gui testing survey
Will Shen
 
Why Test Automation Fails
Ranorex
 
Automated Test Case Generation and Execution from Models
Dharmalingam Ganesan
 
Ad

Similar to Automation Abstraction Layers: Page Objects and Beyond (20)

PDF
Automation Abstractions: Page Objects and Beyond
TechWell
 
PDF
Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...
Iakiv Kramarenko
 
PDF
Javascript ui for rest services
Ioan Eugen Stan
 
PDF
Top100summit 谷歌-scott-improve your automated web application testing
drewz lin
 
PDF
Node.js and Selenium Webdriver, a journey from the Java side
Mek Srunyu Stittri
 
PDF
Selenium RC: Automated Testing of Modern Web Applications
qooxdoo
 
PDF
Easy tests with Selenide and Easyb
Iakiv Kramarenko
 
PDF
Web ui testing
Radim Pavlicek
 
DOCX
Selenium Testing Training in Bangalore
rajkamal560066
 
PPTX
Automation - web testing with selenium
Tzirla Rozental
 
PDF
Hybrid App using WordPress
Haim Michael
 
PPTX
Improving Your Selenium WebDriver Tests - Belgium testing days_2016
Roy de Kleijn
 
KEY
Javascript unit testing, yes we can e big
Andy Peterson
 
PDF
The WebView Role in Hybrid Applications
Haim Michael
 
PPTX
Up and Running with ReactJS
Loc Nguyen
 
PDF
Web UI test automation instruments
Artem Nagornyi
 
PPTX
One code Web, iOS, Android
Artem Marchenko
 
PPT
Test strategy for web development
alice yang
 
PPTX
Marcin Wasilczyk - Page objects with selenium
Trójmiejska Grupa Testerska
 
PDF
Ditching jQuery Madison
Hao Luo
 
Automation Abstractions: Page Objects and Beyond
TechWell
 
Three Simple Chords of Alternative PageObjects and Hardcore of LoadableCompon...
Iakiv Kramarenko
 
Javascript ui for rest services
Ioan Eugen Stan
 
Top100summit 谷歌-scott-improve your automated web application testing
drewz lin
 
Node.js and Selenium Webdriver, a journey from the Java side
Mek Srunyu Stittri
 
Selenium RC: Automated Testing of Modern Web Applications
qooxdoo
 
Easy tests with Selenide and Easyb
Iakiv Kramarenko
 
Web ui testing
Radim Pavlicek
 
Selenium Testing Training in Bangalore
rajkamal560066
 
Automation - web testing with selenium
Tzirla Rozental
 
Hybrid App using WordPress
Haim Michael
 
Improving Your Selenium WebDriver Tests - Belgium testing days_2016
Roy de Kleijn
 
Javascript unit testing, yes we can e big
Andy Peterson
 
The WebView Role in Hybrid Applications
Haim Michael
 
Up and Running with ReactJS
Loc Nguyen
 
Web UI test automation instruments
Artem Nagornyi
 
One code Web, iOS, Android
Artem Marchenko
 
Test strategy for web development
alice yang
 
Marcin Wasilczyk - Page objects with selenium
Trójmiejska Grupa Testerska
 
Ditching jQuery Madison
Hao Luo
 
Ad

More from Alan Richardson (20)

PDF
Add More Security To Your Testing and Automating - Saucecon 2021
Alan Richardson
 
PDF
Automating to Augment Testing
Alan Richardson
 
PDF
Open source tools - Test Management Summit - 2009
Alan Richardson
 
PDF
Automating Tactically vs Strategically SauceCon 2020
Alan Richardson
 
PDF
The Future of Testing Webinar
Alan Richardson
 
PDF
Devfest 2019-slides
Alan Richardson
 
PDF
Secrets and Mysteries of Automated Execution Keynote slides
Alan Richardson
 
PDF
Automating Pragmatically - Testival 20190604
Alan Richardson
 
PDF
Joy of Coding Conference 2019 slides - Alan Richardson
Alan Richardson
 
PDF
Programming katas for Software Testers - CounterStrings
Alan Richardson
 
PDF
Technology Based Testing
Alan Richardson
 
PDF
About Consultant Alan Richardson Compendium Developments Evil Tester
Alan Richardson
 
PDF
Shift left-testing
Alan Richardson
 
PDF
Automating and Testing a REST API
Alan Richardson
 
PDF
Technical and Testing Challenges: Using the "Protect The Square" Game
Alan Richardson
 
PDF
TDD - Test Driven Development - Java JUnit FizzBuzz
Alan Richardson
 
PDF
If you want to automate, you learn to code
Alan Richardson
 
PDF
How To Test With Agility
Alan Richardson
 
PDF
Your Automated Execution Does Not Have to be Flaky
Alan Richardson
 
PDF
What is Testability vs Automatability? How to improve your Software Testing.
Alan Richardson
 
Add More Security To Your Testing and Automating - Saucecon 2021
Alan Richardson
 
Automating to Augment Testing
Alan Richardson
 
Open source tools - Test Management Summit - 2009
Alan Richardson
 
Automating Tactically vs Strategically SauceCon 2020
Alan Richardson
 
The Future of Testing Webinar
Alan Richardson
 
Devfest 2019-slides
Alan Richardson
 
Secrets and Mysteries of Automated Execution Keynote slides
Alan Richardson
 
Automating Pragmatically - Testival 20190604
Alan Richardson
 
Joy of Coding Conference 2019 slides - Alan Richardson
Alan Richardson
 
Programming katas for Software Testers - CounterStrings
Alan Richardson
 
Technology Based Testing
Alan Richardson
 
About Consultant Alan Richardson Compendium Developments Evil Tester
Alan Richardson
 
Shift left-testing
Alan Richardson
 
Automating and Testing a REST API
Alan Richardson
 
Technical and Testing Challenges: Using the "Protect The Square" Game
Alan Richardson
 
TDD - Test Driven Development - Java JUnit FizzBuzz
Alan Richardson
 
If you want to automate, you learn to code
Alan Richardson
 
How To Test With Agility
Alan Richardson
 
Your Automated Execution Does Not Have to be Flaky
Alan Richardson
 
What is Testability vs Automatability? How to improve your Software Testing.
Alan Richardson
 

Recently uploaded (20)

PDF
Build It, Buy It, or Already Got It? Make Smarter Martech Decisions
bbedford2
 
PDF
Linux Certificate of Completion - LabEx Certificate
VICTOR MAESTRE RAMIREZ
 
PPTX
Transforming Mining & Engineering Operations with Odoo ERP | Streamline Proje...
SatishKumar2651
 
PDF
Unlock Efficiency with Insurance Policy Administration Systems
Insurance Tech Services
 
PDF
The 5 Reasons for IT Maintenance - Arna Softech
Arna Softech
 
PDF
Open Chain Q2 Steering Committee Meeting - 2025-06-25
Shane Coughlan
 
PPTX
Help for Correlations in IBM SPSS Statistics.pptx
Version 1 Analytics
 
PDF
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pdf
Varsha Nayak
 
PDF
[Solution] Why Choose the VeryPDF DRM Protector Custom-Built Solution for You...
Lingwen1998
 
PDF
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
PPTX
ChiSquare Procedure in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
PPTX
Change Common Properties in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
PDF
HiHelloHR – Simplify HR Operations for Modern Workplaces
HiHelloHR
 
PDF
Download Canva Pro 2025 PC Crack Full Latest Version
bashirkhan333g
 
PPTX
Empowering Asian Contributions: The Rise of Regional User Groups in Open Sour...
Shane Coughlan
 
PDF
유니티에서 Burst Compiler+ThreadedJobs+SIMD 적용사례
Seongdae Kim
 
PDF
IDM Crack with Internet Download Manager 6.42 Build 43 with Patch Latest 2025
bashirkhan333g
 
PDF
Wondershare PDFelement Pro Crack for MacOS New Version Latest 2025
bashirkhan333g
 
PPTX
Agentic Automation: Build & Deploy Your First UiPath Agent
klpathrudu
 
PPTX
Homogeneity of Variance Test Options IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Build It, Buy It, or Already Got It? Make Smarter Martech Decisions
bbedford2
 
Linux Certificate of Completion - LabEx Certificate
VICTOR MAESTRE RAMIREZ
 
Transforming Mining & Engineering Operations with Odoo ERP | Streamline Proje...
SatishKumar2651
 
Unlock Efficiency with Insurance Policy Administration Systems
Insurance Tech Services
 
The 5 Reasons for IT Maintenance - Arna Softech
Arna Softech
 
Open Chain Q2 Steering Committee Meeting - 2025-06-25
Shane Coughlan
 
Help for Correlations in IBM SPSS Statistics.pptx
Version 1 Analytics
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pdf
Varsha Nayak
 
[Solution] Why Choose the VeryPDF DRM Protector Custom-Built Solution for You...
Lingwen1998
 
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
ChiSquare Procedure in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
Change Common Properties in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
HiHelloHR – Simplify HR Operations for Modern Workplaces
HiHelloHR
 
Download Canva Pro 2025 PC Crack Full Latest Version
bashirkhan333g
 
Empowering Asian Contributions: The Rise of Regional User Groups in Open Sour...
Shane Coughlan
 
유니티에서 Burst Compiler+ThreadedJobs+SIMD 적용사례
Seongdae Kim
 
IDM Crack with Internet Download Manager 6.42 Build 43 with Patch Latest 2025
bashirkhan333g
 
Wondershare PDFelement Pro Crack for MacOS New Version Latest 2025
bashirkhan333g
 
Agentic Automation: Build & Deploy Your First UiPath Agent
klpathrudu
 
Homogeneity of Variance Test Options IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 

Automation Abstraction Layers: Page Objects and Beyond

  • 1. 1 Automation Abstractions: Page Objects and Beyond Alan Richardson @eviltester https://xp-dev.com/svn/AutomationAbstractions www.SeleniumSimplified.com www.EvilTester.com www.CompendiumDev.co.uk www.JavaForTesters.com
  • 2. 2 What is Abstraction? ● Modelling ● Separation of concerns ● Logical vs Physical ● Functional vs Structural ● Interfaces vs Implementations ● Data / Entities / Persistence ● Functionality / Task Flow ● Goals / Strategies ● Layers – GUI, DB, HTTP ● Etc.
  • 3. “I must create a system. or be enslav'd by another Mans; I will not reason & compare: my business is to create” William Blake, 1820 Jerusalem: The Emanation of the Giant Albion 3 http://www.blakearchive.org/exist/blake/archive/object.xq?objectid=jerusalem.e.illbk.10&java=no
  • 4. https://xp-dev.com/svn/AutomationAbstractions 4 Example Test Without Abstraction @Before public void startDriver(){ @Test public void canCreateAToDoWithNoAbstraction(){ driver.get("http://todomvc.com/architecture-examples/backbone/"); int originalNumberOfTodos = driver.findElements( By.cssSelector("ul#todo-list li")).size(); WebElement createTodo = driver.findElement(By.id("new-todo")); createTodo.click(); createTodo.sendKeys("new task"); createTodo.sendKeys(Keys.ENTER); assertThat(driver.findElement( By.id("filters")).isDisplayed(), is(true)); int newToDos = driver.findElements( By.cssSelector("ul#todo-list li")).size(); assertThat(newToDos, greaterThan(originalNumberOfTodos)); } driver = new FirefoxDriver(); } @After public void stopDriver(){ driver.close(); driver.quit(); } NoAbstractionTest.java
  • 5. But this does use some abstraction layers LLooccaattoorr A Abbssttrraaccttioionns WebElement Generic Element Abstraction 5 Example Test Without Abstraction @Before public void startDriver(){ WebDriver Generic Browser Abstraction @Test public void canCreateAToDoWithNoAbstraction(){ Firefox Browser Abstraction driver.get("http://todomvc.com/architecture-examples/backbone/"); int originalNumberOfTodos = driver.findElements( By.cssSelector("ul#todo-list li")).size(); WebElement createTodo = driver.findElement(By.id("new-todo")); createTodo.click(); createTodo.sendKeys("new task"); createTodo.sendKeys(Keys.ENTER); assertThat(driver.findElement( By.id("filters")).isDisplayed(), is(true)); int newToDos = driver.findElements( Manipulation Abstractions By.cssSelector("ul#todo-list li")).size(); assertThat(newToDos, greaterThan(originalNumberOfTodos)); } driver = new FirefoxDriver(); } @After public void stopDriver(){ driver.close(); driver.quit(); } NoAbstractionTest.java
  • 6. 6 WebDriver provides abstractions ● Browser ● DOM ● Web Element Tool vendors gain value from generic abstractions. You gain value from 'domain' abstractions.
  • 7. 7 Example Test With Abstraction @Before public void startDriver(){ @Test public void canCreateAToDoWithAbstraction(){ TodoMVCUser user = new TodoMVCUser(driver, new TodoMVCSite()); user.opensApplication().and().createNewToDo("new task"); ApplicationPageFunctional page = new ApplicationPageFunctional(driver, new TodoMVCSite()); assertThat(page.getCountOfTodoDoItems(), is(1)); assertThat(page.isFooterVisible(), is(true)); } driver = new FirefoxDriver(); } @After public void stopDriver(){ driver.close(); driver.quit(); } NoAbstractionTest.java
  • 8. 8 Why Abstraction? ● Change implementations ● Single Responsibility – only changes when necessary ● Makes automation readable and maintainable ● We can unit test some of our test code ● etc. https://xp-dev.com/svn/AutomationAbstractions
  • 9. 9 Some Abstraction Layer Categories 1) Data – Generic Data Abstractions e.g. email, postcode 2) Physical – Physical layout of your application e.g. pages, components – Navigation across pages 3) Domain – Your application Entities domain e.g. user, account 4) Logical – User actions, workflows
  • 10. 10 Common Automation Abstractions ● Page Objects: pages, components, widgets ● Dom Element Abstractions: select, textbox, etc. ● Domain Objects: user, account, order ● Gherkin (Given/When/And/Then) ● Domain Specific Languages: code, keywords ● ... https://xp-dev.com/svn/AutomationAbstractions
  • 11. 11 Abstraction != Implementation ● Abstraction != Tool / Framework / Implementation ● Gherkin != Cucumber ● Page Object != Page Factory / Slow Loadable ● DSL != Keyword Driven If we want to get good at abstraction then we need to model, split apart, make the relationships clear, and be aware of our options.
  • 12. 12 Page Objects ● The most obvious automation abstraction ● What is it? – A page? A Component? ● Do web applications still have pages?
  • 13. A Page Object that abstracts a Page 13 ● Often has methods for – Opening the page – Accessing elements – Doing stuff, and navigating as a side-effect – Logical high level functionality e.g. login – Low level physical functionality e.g. typeUsername, clickLoginButton Should a Page Object be responsible for all of this?
  • 14. 14 Page Object Design Decisions ● What methods does it have? – Functional ● login(username, password), ● loginAs(user) – Structural ● enterName(username), enterPassword(password), clickLogin(), submitLoginForm(username, password) ● Does it expose elements or not? – public WebElement loginButton; – public WebElement getLoginButton(); – public clickLoginButton();
  • 15. 15 Page Object Functionality Approaches ● Expose WebElements Directly – Leads to WebElement Abstractions – public TextField userNameField; ● Hide WebElements behind physical functional methods e.g. typeUserName("bob"); ● Logical helper methods e.g. loginAs(name,pass) ● Layers of Page Objects – Physical – Logical
  • 16. 16 Navigation Design Decisions ● Does a Page Object return other pages? public IssueListPage submit(){ driver.findElement(By.id(“submit”)).click(); return new IssueListPage(driver); } ● Or Navigate implicitly after interactions ● Or have navigation objects
  • 17. 17 Implicit or Explicit Wait? ● Implicit Wait driver.manage().timeouts(). implicitlyWait(15L, TimeUnit.SECONDS); assertThat(driver.findElement( By.id("filters")).isDisplayed() , is(true)); ● Explicit Wait driver.manage().timeouts(). implicitlyWait(0L, TimeUnit.SECONDS); WebDriverWait wait = new WebDriverWait(driver,15); wait.until(ExpectedConditions.elementToBeClickable (By.id("filters"))); Example: 'NoAbstractionTest.java'
  • 18. 18 Implementing Page Objects ● POJO – Plain object, driver in constructor, methods use driver.<method> ● Page Factory – Annotated elements, lazy instantiation via reflection ● LoadableComponent – Common interface (load, isLoaded), isLoaded throws Error ● SlowLoadableComponent – Common interface, waits for on isLoaded ● Other approaches?
  • 19. 19 Example Implementations https://xp-dev.com/svn/AutomationAbstractions
  • 20. 20 POJO ● 'ApplicationPage.java' – Used in 'SequentialCreationOfTest.java' – Not much refactoring in the example ● Simple Class ● WebDriver passed to constructor ● Composition of any components ● e.g. – com.seleniumsimplified.todomvc.page.pojo – 'ApplicationPage.java' ● Not much refactoring in the example
  • 22. 22 Functional vs Structural ● Functional – loginAs(username, password) ● Structural – enterUsername – enterPassword – clickLoginButton – submitLoginForm(username, password)
  • 23. 23 Functional Vs Structural Example ● One way of answering “what methods to put on a page object” – Is it functional / behavioural? – Is it structural / Physical? ● Functional 'uses' Structural implementation ● Why? – Sometimes it is just a naming difference – Handling exceptions in functional but not structural – Higher level methods in Functional – Different concepts e.g. deleteLastItem
  • 24. 24 Page Factory ● Annotate fields with @FindBy ● Instantiate in constructor using PageFactory.initElements – Can create your own page factory initialiser ● Avoids boilerplate accessor methods ● Fast to create Page Objects ● Might become harder to expand and maintain
  • 25. 25 Page Factory Example @FindBy(how = How.CSS, using="#todo-count strong") private WebElement countElementStrong; @FindBy(how = How.CSS, using="#todo-count") private WebElement countElement; @FindBy(how = How.CSS, using="#filters li a") List<WebElement> filters; @FindBy(how = How.ID, using="clear-completed") List<WebElement> clearCompletedAsList; @FindBy(how = How.ID, using="clear-completed") WebElement clearCompletedButton; public ApplicationPageStructuralFactory(WebDriver driver, TodoMVCSite todoMVCSite) { PageFactory.initElements(driver, this); this.driver = driver; ...
  • 26. 26 SlowLoadableComponent ● Some pages and components need synchronisation to wait till they are ready – One approach – SlowLoadableComponent adds responsibility for waiting, to the page ● extend SlowLoadableComponent ● Standard interface for synchronisation on load – get() ● If isLoaded then return this Else load ● While not loaded{ wait for 200 millseconds} – Implement load and isLoaded
  • 27. 27 Fluent Page Objects todoMVC = new ApplicationPageFunctionalFluent( driver, todoMVCSite); todoMVC.get(); todoMVC.enterNewToDo("First Completed Item"). and(). toggleCompletionOfLastItem(). then(). enterNewToDo("Still to do this"). and(). enterNewToDo("Still to do this too"). then(). filterOnCompleted();
  • 28. 28 Fluent Page Objects ● Methods return the page object or other objects instead of void – void clickDeleteButton(); – PageObject clickDeleteButton(); ● Syntactic sugar methods: – and(), then(), also() ● Can work well at high levels of abstraction and when no navigation involved ● Train Wreck?
  • 29. Navigation Options 29 ● Direct in Test: page.get(); page.waitFor(); ● Instantiate new pages based on test flow – Navigation as side-effect, may have to bypass 'get' – Loadable pages, non-loadable, support classes ● Page Object methods might return other Pages – e.g. a method on the login page might be ● MyAccountPage clickLogin(); ● We might use navigation objects – direct, Jump.to(MyAccountPage.class) – path based (current page → desired page) ● Navigate.to(MyAccountPage.class)
  • 30. 30 Possible Domain Abstractions ● Logical Objects – ToDo – ToDoList ● Physical Objects – LocallyStoredToDo ● Actors – User ● Environment – Site – Implementation
  • 31. 31 Page Objects & Domain Objects ● Instead of – todoMVC.enterNewToDo(“New Item”) ● We could have have – ToDoItem newItem = new ToDoItem(“New Item”); – todoMVC.enterNewToDo(newItem); ● See code in DomainBasedTest
  • 32. 32 Domain Objects That Span Logical & Physical e.g. User ● user.createNewToDo(“new item”) ● user.createNewToDo(newItem) ● See use in NoAbstractionTest
  • 33. 33 Sometimes it is possible to over think this stuff ● Don't let thinking about this slow you down ● Conduct experiments ● Refactor ● Rethink if – you are maintaining too much – your abstraction layer stops you doing stuff – you are 'working around' your abstraction layers
  • 35. 35 Element Abstraction Example public interface Checkbox { public boolean isChecked(); public Checkbox check(); public Checkbox uncheck(); public Checkbox toggle(); } ● Would you include 'toggle'? https://xp-dev.com/svn/AutomationAbstractions
  • 36. 36 Element Abstractions ● Existing support classes: Select, ● Possible: TextBox, Checkbox, TextBox, File etc. ● Can enforce Semantics – Checkbox: isChecked, check(), uncheck(), toggle() – TextBox: clear(), enterText() – etc. ● Pass back from Page Objects into test?
  • 37. Element Abstraction Pros and Cons 37 ● May have to create a custom page factory ● Can help 'restrict' code i.e. check or uncheck, rather than click, enforces 'semantics' ● If you create them... – allow return WebElement ● so that I can go beyond the abstraction layer if I need to. Not required if it is just a WebElement wrapper. https://xp-dev.com/svn/AutomationAbstractions
  • 38. 38 Component Abstractions ● Shared Components/Widgets on the page ● e.g. – VisibleToDoEntry, VisibleToDoList – Filters, Footer, Header, etc. ● Could have 'functional' representation for repeated items e.g. login forms ● Could have 'structural' representation ● Likely use : page object composition
  • 39. 39 Component Abstraction Example TodoEntry todo = page.getToDoEntryAt(lastItemPosition); todo.markCompleted(); Instead of page.markTodoCompleted(lastItemPosition);
  • 40. 40 Gherkin as an abstraction layer Feature: We can create and edit To Do lists in ToDoMvc We want to amend todos in ToDoMVC because that is the set of exercises on the abstraction tutorial Scenario: Create a ToDo Item Given a user opens a blank ToDoMVC page When the user creates a todo "new task" Then they see 1 todo item on the page ● Implement steps using highest appropriate abstraction layer ● CucumberJVM as 'DSL implementor' ● 'Expressibility' vs 'Step Re-use' ● See todomvc.feature and ToDoMvcSteps
  • 41. 41 My modeling biases ● Driver – Inject so instantiate any page or component as required/desired at any time ● Explicit Synchronisation – To make sure that the desired object is available and ready for use (as defined by synchronisation) ● Navigation – Implicit (via taking action e.g. click) – Explicit Navigation Object, not in page object ● Open/jump (via driver.get) ● To (state model from current, to desired)
  • 42. 42 My modeling biases ● Page Objects – Physical ● abstract the 'real world' – Components ● For common features on the page – Logical ● abstract the functionality ● Sometimes these are entity methods not page objects – e.g. user.registers().and().logsin() ● I tend not to.... – abstract WebElements
  • 43. 43 My modeling biases ● I tend not to.... – abstract WebElements – Use inheritence to create a model of the app ● e.g. MyAppPage extends GenericAppPage – Use 3rd party abstractions on top of WebDriver
  • 44. 44 Are there rights and wrongs? ● Right / Wrong? ● Decisions? ● Project/Team/Organisation Standards? Identify your own biases - Experiment Recognise your decisions
  • 45. 45 Decisions ● The 'limits' and overlap of Abstraction Layers ● Build it now, or 'refactor to' later ● How much change is anticipated? – To which layer? GUI, Business domain, Workflow? ● Who is working with the automation code? – Skill levels? Support needed? ● How/When with the automation execute?
  • 46. 46 Other Useful Links ● Jeff “Cheezy” Morgan – page-object ruby gem, data_magic gem and stareast code – https://github.com/cheezy?tab=repositories ● Marcus Merrell – Self-Generating Test Artifacts for Selenium/WebDriver – https://www.youtube.com/watch?v=mSCFsUOgPpw ● Anand Ramdeo – One Step at a Time – https://www.youtube.com/watch?v=dFPgzH_XP1I https://xp-dev.com/svn/AutomationAbstractions
  • 47. 47 Homework ● Using the code at https://xp-dev.com/svn/AutomationAbstractions/ – Compare the different implementations under 'main' ● com.seleniumsimplified.todomvc.page – Investigate how the Page Objects delegate to each other, and the Domain Objects use Page Objects – Examine the 'test' usage of the Page Objects and Domain Objects – Examine the different navigation approaches
  • 48. 48 Blogs and Websites ● CompendiumDev.co.uk ● SeleniumSimplified.com ● EvilTester.com ● JavaForTesters.com ● Twitter: @eviltester Online Training Courses ● Technical Web Testing 101 Unow.be/at/techwebtest101 ● Intro to Selenium Unow.be/at/startwebdriver ● Selenium 2 WebDriver API Unow.be/at/webdriverapi Videos youtube.com/user/EviltesterVideos Books Selenium Simplified Unow.be/rc/selsimp Java For Testers leanpub.com/javaForTesters Alan Richardson uk.linkedin.com/in/eviltester Independent Test Consultant & Custom Training Contact Alan http://compendiumdev.co.uk/contact