SlideShare a Scribd company logo
SCREENPLAY

A Journey Beyond The PageObject Pattern

Antony Marcano

Jan Molak

Kostas Mamalis
CONTACT
•

Kostas Mamalis
@agiletestinguk

kostas@masterthought.net
•

Antony Marcano
@AntonyMarcano

antony@riverglide.com
•

Jan Molak
@JanMolak

jan.molak@smartcodeltd.co.uk
CONTEXT
IN THE BEGINNING
•

Long established financial institution

•

Used Scrum with 2 week Sprints

•

Outsourced development to large consultancy

•

No automated acceptance tests (few unit tests)
ALONG THE JOURNEY
•

Realised that automated tests were essential

•

Wrote lots of Cucumber tests

•

Backed by Selenium/WebDriver

•

Used the PageObject Pattern
SELENIUM
AND
THE PAGE OBJECT PATTERN
Illustrated with the Pet Clinic
A journey beyond the page object pattern
TESTING THE PET CLINIC
WEBDRIVER EXAMPLE
DesiredCapabilities capabilities = new DesiredCapabilities();
WebDriver driver = new PhantomJSDriver(desiredCapabilities());
driver.get(baseUrl+"owners/find.html");
driver.findElement(By.cssSelector("#search-owner-form button")).click();
assertThat(
driver.findElements(By.cssSelector("owners tbody tr")).size(),
is(10)
);
FINDING ALL OWNERS - WEBDRIVER EXAMPLE
DesiredCapabilities capabilities = new DesiredCapabilities();
WebDriver driver = new PhantomJSDriver(desiredCapabilities());
driver.get(baseUrl+"owners/find.html");
driver.findElement(By.cssSelector("#search-owner-form button")).click();
assertThat(
driver.findElements(By.cssSelector("owners tbody tr")).size(),
is(10)
);
FINDING ALL OWNERS - PAGEOBJECT EXAMPLE
DesiredCapabilities capabilities = new DesiredCapabilities();
WebDriver driver = new PhantomJSDriver(desiredCapabilities());
driver.get(baseUrl+"owners/find.html");
FindOwnersPage findOwners =
PageFactory.initElements(driver, FindOwnersPage.class);
OwnersPage owners = findOwners.findWith(EMPTY_SEARCH_TERMS);
assertThat(owners.numberOfOwners(), is(10));
PROBLEMS AROSE
•

Large PageObject classes

•

Brittle test-code (less than raw Selenium)

•

Duplication across PageObjects for each of the
‘portals’
THEY TRIED THE FOLLOWING
•

Separate behaviour into Navigation Classes

•

Reduce duplication with inheritance

Causing ...
•

Large Navigation classes

•

Deep inheritance hierarchy
EFFECTS ON THE TEAM
•

Took longer and longer to add new tests

•

Got harder to diagnose problems

•

Low trust in the ‘test framework’ and Cucumber

•

Reduced faith
in automated testing

•

Impacted morale
WHAT WAS THE ANSWER?
Antony Marcano at first AAFTT in 2007
THE INSIGHT
Roles
← Who
➥ Goals
← Why
➥ Tasks
← What
➥ Actions ← How
Inspired by Kevin Lawrence’s talk at the first AAFTT in 2007
More of his thinking here: http://www.developertesting.com/archives/month200710/20071013-In%20Praise%20of
%20Abstraction.html
2008 - JNARRATE
@Test
public void should_be_able_to_edit_a_page() {
Given.thatThe(wiki).wasAbleTo(beAtThe(PointWhereItHasBeen.JUST_INSTALLED));
And.thatThe(user).wasAbleTo(navigateToTheHomePage());
And.thatThe(user).wasAbleTo(navigateToTheHomePage());
When.the(user).attemptsTo(

tas
k

changeTheContent().to("Welcome to Acceptance Test Driven Development")

tas
k

);

Then.the(textOnTheScreen().ofThe(user)).

tas
k
shouldBe("Welcome to Acceptance Test Driven Development");
}
Playing with fluent APIs and started to explore the model of Tasks & Actions
(although back then the labels I used more like Kevin’s labels).
2009 - SCREENPLAY - A TASK
public void perform() {
you.need(To.doTheFollowing( // actions
Click.onThe(OptionsMenu.EDIT_BUTTON),
ClearTheContent.ofThe(Editor.CONTENT_PANEL),
Type.theText(newContent).
intoThe(Editor.CONTENT_PANEL),
Click.onThe(Editor.SAVE_BUTTON)
));
}
2012 - THE JOURNEY PATTERN
Actor

performs

Tasks

has

Abilities

composed of

enable

Actions

interact with

Screen
contains

Elements
JOURNEY PATTERN APPLIED
JUNIT
Roles
➥ Goals

➥ Tasks

← Who
← Why

← What

➥ Actions ← How

Actor theReceptionist =
new Actor().with(WebBrowsing.ability());
@Test public void
should_find_all_owners_by_default

theReceptionist.attemptsTo(
Go.to(findOwnersScreen.url()),
Search.forOwnersWith(EMPTY_SEARCH_TERMS),
Count.theNumberOfOwners()
);
Enter.the(searchTerms).
into(findOwnersScreen.searchTerms),
Click.onThe(findOwnersScreen.searchButton)
JOURNEY PATTERN APPLIED
CUCUMBER
Roles

← Who

As a Pet Clinic Receptionist

➥ Goals

← Why

Scenario: Find all owners by default

← What

When I search for owners with BLANK search terms
@When
(“^I search for owners with BLANK search terms$”)

➥ Tasks

theReceptionist.attemptsTo(
Search.forOwnersWith(EMPTY_SEARCH_TERMS)
);

➥ Actions ← How

Enter.the(searchTerms).
into(findOwnersScreen.searchTerms),
PUTTING IT ALL TOGETHER
Actor theReceptionist = new Actor().with(WebBrowsing.ability());
theReceptionist.attemptsTo(
Go.to(findOwnersScreen.url()),
Search.forOwnersWith(EMPTY_SEARCH_TERMS),
Count.theNumberOfOwners()
);
assertThat(
theReceptionist.sawThatThe(numberOfOwners()),
was(theExpectedNumberOfOwners)
);
A TASK
…
private static String searchTerms;
@Override
public void performAs(Actor asAReceptionist) {
asAReceptionist.attemptTo(
Enter.the(searchTerms).into(findOwnersScreen.searchTerms),
Click.onThe(findOwnersScreen.searchButton)
);
}
public SearchForOwnersWith(String searchTerms) {
this.searchTerms = searchTerms;
}
…
A SCREEN

@Url("owners/find.html")
public class FindOwnersScreen extends WebScreen {
@LocateBy(css="#search-owner-form input")
public ScreenElement searchTerms;
@LocateBy(css="#search-owner-form button")
public ScreenElement searchButton;
}
AN ACTION
public class Enter extends WebDriverInteraction implements Perform {
private String text;
private ScreenElement field;
public void performAs(Actor actor) {
web(actor).findElement(field.locator()).sendKeys(text);
}
public Enter(String text) { this.text = text; }
public static Enter the(String text) {return new Enter(text);}
public Perform into(ScreenElement field) {
this.field = field;
return this;
}
}
PROBLEMS SOLVED
•

Smaller “Screen” classes

•

Small, focused “Task” classes

•

Readable code

•

Consistent metaphor

•

Minimal inheritance

•

Removed need for duplication across behaviours previously in
PageObjects or “Navigation” classes
DESIGN PRINCIPLES
•

DRY - navigational steps in one place

•

Separation of Concerns - Page Structure and Actions separate

•

Small Classes - easy to comprehend

•

Single Responsibility - classes focused on one thing
and one thing only

•

Minimise conditional logic - navigational if-thens replaced
with composable sequences
SCREENPLAY REVIVED
Under development for everyone to use
Watch This Space!
CONTACT
•

Kostas Mamalis
@agiletestinguk

kostas@masterthought.net
•

Antony Marcano
@AntonyMarcano

antony@riverglide.com
•

Jan Molak
@JanMolak

jan.molak@smartcodeltd.co.uk
THANK YOU!

More Related Content

What's hot (20)

PDF
React new features and intro to Hooks
Soluto
 
PDF
React js use contexts and useContext hook
Piyush Jamwal
 
PPTX
Nouveautés de java 8
Florian Beaufumé
 
PPTX
React-JS.pptx
AnmolPandita7
 
PPTX
React state
Ducat
 
PPTX
React hooks
Ramy ElBasyouni
 
PDF
Introduction to RxJS
Brainhub
 
PPTX
Angular 2.0 forms
Eyal Vardi
 
ODP
Xke spring boot
sourabh aggarwal
 
PDF
Spring Security
Knoldus Inc.
 
PDF
TypeScript Introduction
Dmitry Sheiko
 
DOCX
Selenium interview-questions-freshers
Naga Mani
 
PDF
Basics of React Hooks.pptx.pdf
Knoldus Inc.
 
PPT
Spring Boot in Action
Alex Movila
 
PDF
PUC SE Day 2019 - SpringBoot
Josué Neis
 
PPTX
React Class Components vs Functional Components: Which is Better?
Fibonalabs
 
PDF
Building blocks of Angular
Knoldus Inc.
 
PPTX
Java 11 to 17 : What's new !?
Jérôme Tamborini
 
PDF
Angular components
Sultan Ahmed
 
PPT
TypeScript Presentation
Patrick John Pacaña
 
React new features and intro to Hooks
Soluto
 
React js use contexts and useContext hook
Piyush Jamwal
 
Nouveautés de java 8
Florian Beaufumé
 
React-JS.pptx
AnmolPandita7
 
React state
Ducat
 
React hooks
Ramy ElBasyouni
 
Introduction to RxJS
Brainhub
 
Angular 2.0 forms
Eyal Vardi
 
Xke spring boot
sourabh aggarwal
 
Spring Security
Knoldus Inc.
 
TypeScript Introduction
Dmitry Sheiko
 
Selenium interview-questions-freshers
Naga Mani
 
Basics of React Hooks.pptx.pdf
Knoldus Inc.
 
Spring Boot in Action
Alex Movila
 
PUC SE Day 2019 - SpringBoot
Josué Neis
 
React Class Components vs Functional Components: Which is Better?
Fibonalabs
 
Building blocks of Angular
Knoldus Inc.
 
Java 11 to 17 : What's new !?
Jérôme Tamborini
 
Angular components
Sultan Ahmed
 
TypeScript Presentation
Patrick John Pacaña
 

Viewers also liked (18)

PDF
Serenity and the Journey Pattern
John Ferguson Smart Limited
 
PPTX
Refactoring page objects The Screenplay Pattern
RiverGlide
 
PPTX
ScreenPlay Design Patterns for QA Automation
COMAQA.BY
 
PDF
Beyond Page Objects
Dante Briones
 
PDF
Using The Page Object Pattern
Dante Briones
 
PDF
Page Objects Done Right - selenium conference 2014
Oren Rubin
 
PDF
Perils of Page-Object Pattern
Anand Bagmar
 
PDF
APIs: A Better Alternative to Page Objects
Sauce Labs
 
PPTX
Advanced visual testing of web and mobile applications
Denys Zaiats
 
PDF
CukeUp 2016 Agile Product Planning Workshop
John Ferguson Smart Limited
 
PPTX
DSL, Page Object and WebDriver – the path to reliable functional tests.pptx
Mikalai Alimenkou
 
PPTX
Out of box page object design pattern, java
COMAQA.BY
 
PDF
Better Page Object Handling with Loadable Component Pattern
Sargis Sargsyan
 
PDF
BDD Anti-patterns
John Ferguson Smart Limited
 
PPTX
Webium: Page Objects In Python (Eng)
Uladzimir Franskevich
 
PPTX
DSL, Page Object and Selenium – a way to reliable functional tests
Mikalai Alimenkou
 
PDF
Node.js and Selenium Webdriver, a journey from the Java side
Mek Srunyu Stittri
 
PDF
User Story Mapping, Discover the whole story
Jeff Patton
 
Serenity and the Journey Pattern
John Ferguson Smart Limited
 
Refactoring page objects The Screenplay Pattern
RiverGlide
 
ScreenPlay Design Patterns for QA Automation
COMAQA.BY
 
Beyond Page Objects
Dante Briones
 
Using The Page Object Pattern
Dante Briones
 
Page Objects Done Right - selenium conference 2014
Oren Rubin
 
Perils of Page-Object Pattern
Anand Bagmar
 
APIs: A Better Alternative to Page Objects
Sauce Labs
 
Advanced visual testing of web and mobile applications
Denys Zaiats
 
CukeUp 2016 Agile Product Planning Workshop
John Ferguson Smart Limited
 
DSL, Page Object and WebDriver – the path to reliable functional tests.pptx
Mikalai Alimenkou
 
Out of box page object design pattern, java
COMAQA.BY
 
Better Page Object Handling with Loadable Component Pattern
Sargis Sargsyan
 
BDD Anti-patterns
John Ferguson Smart Limited
 
Webium: Page Objects In Python (Eng)
Uladzimir Franskevich
 
DSL, Page Object and Selenium – a way to reliable functional tests
Mikalai Alimenkou
 
Node.js and Selenium Webdriver, a journey from the Java side
Mek Srunyu Stittri
 
User Story Mapping, Discover the whole story
Jeff Patton
 
Ad

Similar to A journey beyond the page object pattern (20)

PDF
My Test Automation Journey
Vaidas Pilkauskas
 
PDF
Selenium Design Patterns And Best Practices Dima Kovalenko
njamberudito
 
PDF
All the world's a stage – the next step in automated testing practices
John Ferguson Smart Limited
 
PDF
Patterns of Test Automation
vodQA
 
PDF
Design Patterns in Automation Framework.pdf
ArunVastrad4
 
PDF
Mastering UI automation at Scale: Key Lessons and Best Practices (By Fernando...
Applitools
 
PDF
Automation Abstractions: Page Objects and Beyond
TechWell
 
PDF
UI Testing Pattern
David Harrison
 
PDF
Acceptance Testing of Web UI
Vladimir Tsukur
 
ODP
Good Practices On Test Automation
Gustavo Labbate Godoy
 
PDF
Automation Abstraction Layers: Page Objects and Beyond
Alan Richardson
 
PPT
Pa Project And Best Practice 2
alice yang
 
PDF
Bdd Show and Tell
David Harrison
 
PDF
6 Traits of a Successful Test Automation Architecture
Erdem YILDIRIM
 
DOC
Priyanka Sharma
Priyanka Sharma
 
PDF
Stanislaw potoczny kra_qa_21.01.20
kraqa
 
PDF
Page Object Model and Implementation in Selenium
Zoe Gilbert
 
PDF
Patterns of a "Good" Test Automation Framework, Locators & Data
Agile Testing Alliance
 
PDF
Patterns in Test Automation
Anand Bagmar
 
PPTX
Bdd with Cucumber and Mocha
Atish Narlawar
 
My Test Automation Journey
Vaidas Pilkauskas
 
Selenium Design Patterns And Best Practices Dima Kovalenko
njamberudito
 
All the world's a stage – the next step in automated testing practices
John Ferguson Smart Limited
 
Patterns of Test Automation
vodQA
 
Design Patterns in Automation Framework.pdf
ArunVastrad4
 
Mastering UI automation at Scale: Key Lessons and Best Practices (By Fernando...
Applitools
 
Automation Abstractions: Page Objects and Beyond
TechWell
 
UI Testing Pattern
David Harrison
 
Acceptance Testing of Web UI
Vladimir Tsukur
 
Good Practices On Test Automation
Gustavo Labbate Godoy
 
Automation Abstraction Layers: Page Objects and Beyond
Alan Richardson
 
Pa Project And Best Practice 2
alice yang
 
Bdd Show and Tell
David Harrison
 
6 Traits of a Successful Test Automation Architecture
Erdem YILDIRIM
 
Priyanka Sharma
Priyanka Sharma
 
Stanislaw potoczny kra_qa_21.01.20
kraqa
 
Page Object Model and Implementation in Selenium
Zoe Gilbert
 
Patterns of a "Good" Test Automation Framework, Locators & Data
Agile Testing Alliance
 
Patterns in Test Automation
Anand Bagmar
 
Bdd with Cucumber and Mocha
Atish Narlawar
 
Ad

Recently uploaded (20)

PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PPTX
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
PDF
HCIP-Data Center Facility Deployment V2.0 Training Material (Without Remarks ...
mcastillo49
 
PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
PDF
HubSpot Main Hub: A Unified Growth Platform
Jaswinder Singh
 
PDF
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
Complete JavaScript Notes: From Basics to Advanced Concepts.pdf
haydendavispro
 
PDF
Presentation - Vibe Coding The Future of Tech
yanuarsinggih1
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
PDF
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
PDF
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
PDF
Timothy Rottach - Ramp up on AI Use Cases, from Vector Search to AI Agents wi...
AWS Chicago
 
PDF
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PPTX
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
PDF
Blockchain Transactions Explained For Everyone
CIFDAQ
 
PPTX
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
HCIP-Data Center Facility Deployment V2.0 Training Material (Without Remarks ...
mcastillo49
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
HubSpot Main Hub: A Unified Growth Platform
Jaswinder Singh
 
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
Complete JavaScript Notes: From Basics to Advanced Concepts.pdf
haydendavispro
 
Presentation - Vibe Coding The Future of Tech
yanuarsinggih1
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
Timothy Rottach - Ramp up on AI Use Cases, from Vector Search to AI Agents wi...
AWS Chicago
 
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
From Sci-Fi to Reality: Exploring AI Evolution
Svetlana Meissner
 
Blockchain Transactions Explained For Everyone
CIFDAQ
 
AI Penetration Testing Essentials: A Cybersecurity Guide for 2025
defencerabbit Team
 

A journey beyond the page object pattern

  • 1. SCREENPLAY A Journey Beyond The PageObject Pattern Antony Marcano Jan Molak Kostas Mamalis
  • 4. IN THE BEGINNING • Long established financial institution • Used Scrum with 2 week Sprints • Outsourced development to large consultancy • No automated acceptance tests (few unit tests)
  • 5. ALONG THE JOURNEY • Realised that automated tests were essential • Wrote lots of Cucumber tests • Backed by Selenium/WebDriver • Used the PageObject Pattern
  • 6. SELENIUM AND THE PAGE OBJECT PATTERN Illustrated with the Pet Clinic
  • 9. WEBDRIVER EXAMPLE DesiredCapabilities capabilities = new DesiredCapabilities(); WebDriver driver = new PhantomJSDriver(desiredCapabilities()); driver.get(baseUrl+"owners/find.html"); driver.findElement(By.cssSelector("#search-owner-form button")).click(); assertThat( driver.findElements(By.cssSelector("owners tbody tr")).size(), is(10) );
  • 10. FINDING ALL OWNERS - WEBDRIVER EXAMPLE DesiredCapabilities capabilities = new DesiredCapabilities(); WebDriver driver = new PhantomJSDriver(desiredCapabilities()); driver.get(baseUrl+"owners/find.html"); driver.findElement(By.cssSelector("#search-owner-form button")).click(); assertThat( driver.findElements(By.cssSelector("owners tbody tr")).size(), is(10) );
  • 11. FINDING ALL OWNERS - PAGEOBJECT EXAMPLE DesiredCapabilities capabilities = new DesiredCapabilities(); WebDriver driver = new PhantomJSDriver(desiredCapabilities()); driver.get(baseUrl+"owners/find.html"); FindOwnersPage findOwners = PageFactory.initElements(driver, FindOwnersPage.class); OwnersPage owners = findOwners.findWith(EMPTY_SEARCH_TERMS); assertThat(owners.numberOfOwners(), is(10));
  • 12. PROBLEMS AROSE • Large PageObject classes • Brittle test-code (less than raw Selenium) • Duplication across PageObjects for each of the ‘portals’
  • 13. THEY TRIED THE FOLLOWING • Separate behaviour into Navigation Classes • Reduce duplication with inheritance Causing ... • Large Navigation classes • Deep inheritance hierarchy
  • 14. EFFECTS ON THE TEAM • Took longer and longer to add new tests • Got harder to diagnose problems • Low trust in the ‘test framework’ and Cucumber • Reduced faith in automated testing • Impacted morale
  • 15. WHAT WAS THE ANSWER?
  • 16. Antony Marcano at first AAFTT in 2007
  • 17. THE INSIGHT Roles ← Who ➥ Goals ← Why ➥ Tasks ← What ➥ Actions ← How Inspired by Kevin Lawrence’s talk at the first AAFTT in 2007 More of his thinking here: http://www.developertesting.com/archives/month200710/20071013-In%20Praise%20of %20Abstraction.html
  • 18. 2008 - JNARRATE @Test public void should_be_able_to_edit_a_page() { Given.thatThe(wiki).wasAbleTo(beAtThe(PointWhereItHasBeen.JUST_INSTALLED)); And.thatThe(user).wasAbleTo(navigateToTheHomePage()); And.thatThe(user).wasAbleTo(navigateToTheHomePage()); When.the(user).attemptsTo( tas k changeTheContent().to("Welcome to Acceptance Test Driven Development") tas k ); Then.the(textOnTheScreen().ofThe(user)). tas k shouldBe("Welcome to Acceptance Test Driven Development"); } Playing with fluent APIs and started to explore the model of Tasks & Actions (although back then the labels I used more like Kevin’s labels).
  • 19. 2009 - SCREENPLAY - A TASK public void perform() { you.need(To.doTheFollowing( // actions Click.onThe(OptionsMenu.EDIT_BUTTON), ClearTheContent.ofThe(Editor.CONTENT_PANEL), Type.theText(newContent). intoThe(Editor.CONTENT_PANEL), Click.onThe(Editor.SAVE_BUTTON) )); }
  • 20. 2012 - THE JOURNEY PATTERN Actor performs Tasks has Abilities composed of enable Actions interact with Screen contains Elements
  • 21. JOURNEY PATTERN APPLIED JUNIT Roles ➥ Goals ➥ Tasks ← Who ← Why ← What ➥ Actions ← How Actor theReceptionist = new Actor().with(WebBrowsing.ability()); @Test public void should_find_all_owners_by_default theReceptionist.attemptsTo( Go.to(findOwnersScreen.url()), Search.forOwnersWith(EMPTY_SEARCH_TERMS), Count.theNumberOfOwners() ); Enter.the(searchTerms). into(findOwnersScreen.searchTerms), Click.onThe(findOwnersScreen.searchButton)
  • 22. JOURNEY PATTERN APPLIED CUCUMBER Roles ← Who As a Pet Clinic Receptionist ➥ Goals ← Why Scenario: Find all owners by default ← What When I search for owners with BLANK search terms @When (“^I search for owners with BLANK search terms$”) ➥ Tasks theReceptionist.attemptsTo( Search.forOwnersWith(EMPTY_SEARCH_TERMS) ); ➥ Actions ← How Enter.the(searchTerms). into(findOwnersScreen.searchTerms),
  • 23. PUTTING IT ALL TOGETHER Actor theReceptionist = new Actor().with(WebBrowsing.ability()); theReceptionist.attemptsTo( Go.to(findOwnersScreen.url()), Search.forOwnersWith(EMPTY_SEARCH_TERMS), Count.theNumberOfOwners() ); assertThat( theReceptionist.sawThatThe(numberOfOwners()), was(theExpectedNumberOfOwners) );
  • 24. A TASK … private static String searchTerms; @Override public void performAs(Actor asAReceptionist) { asAReceptionist.attemptTo( Enter.the(searchTerms).into(findOwnersScreen.searchTerms), Click.onThe(findOwnersScreen.searchButton) ); } public SearchForOwnersWith(String searchTerms) { this.searchTerms = searchTerms; } …
  • 25. A SCREEN @Url("owners/find.html") public class FindOwnersScreen extends WebScreen { @LocateBy(css="#search-owner-form input") public ScreenElement searchTerms; @LocateBy(css="#search-owner-form button") public ScreenElement searchButton; }
  • 26. AN ACTION public class Enter extends WebDriverInteraction implements Perform { private String text; private ScreenElement field; public void performAs(Actor actor) { web(actor).findElement(field.locator()).sendKeys(text); } public Enter(String text) { this.text = text; } public static Enter the(String text) {return new Enter(text);} public Perform into(ScreenElement field) { this.field = field; return this; } }
  • 27. PROBLEMS SOLVED • Smaller “Screen” classes • Small, focused “Task” classes • Readable code • Consistent metaphor • Minimal inheritance • Removed need for duplication across behaviours previously in PageObjects or “Navigation” classes
  • 28. DESIGN PRINCIPLES • DRY - navigational steps in one place • Separation of Concerns - Page Structure and Actions separate • Small Classes - easy to comprehend • Single Responsibility - classes focused on one thing and one thing only • Minimise conditional logic - navigational if-thens replaced with composable sequences
  • 29. SCREENPLAY REVIVED Under development for everyone to use Watch This Space!

Editor's Notes

  • #6: New requirement for automated testing -> tests focused on UI -> inverted test pyramid
  • #7: 1. Let’s refresh our memory what the Page Object pattern is all about 2. AUDIENCE: Can we have a show of hands; how many of you work with Selenium? Webdriver? Selenium IDE?  3. OK, so let's see how functional testing of the UI can be addressed using an example of a serious, financial application ...
  • #8: Because of confidentiality reasons we can't present our client's applications, but I believe that even a much simpler project will be enough to demonstrate the limitations of two common approaches to UI testing. I'll leave re-scaling the problem to the size of your typical projects to your imagination.
  • #9: Let's talk about testing the PetClinic, a sample Spring application that demonstrates the basic of using the Spring framework.
  • #10: We have some people with WebDriver experience here. So guys, what is this test trying to prove?
  • #11: So the scenario we have here: a PetClinic Receptionist wants to use the default behaviour of the Search form, which allows them to see all the data stored in the database if no search terms are specified. Now, how clear is this scenario based on this code?It’s difficult to tell what the test is trying to prove with all the css selector noise
  • #12: PageObjects introduce a basic abstraction that encapsulates page elements and actions that can be performed on a given page in a PageObject; Actions return other PageObjects -> maintenance overhead should the flow change They might encourage code duplication -> what if you can log in on different pages?