SlideShare ist ein Scribd-Unternehmen logo
1 von 31
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
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!

Weitere ähnliche Inhalte

Was ist angesagt?

Test automation using selenium
Test automation using seleniumTest automation using selenium
Test automation using selenium
shreyas JC
 
Selenium Tutorial For Beginners | Selenium Automation Testing Tutorial | Sele...
Selenium Tutorial For Beginners | Selenium Automation Testing Tutorial | Sele...Selenium Tutorial For Beginners | Selenium Automation Testing Tutorial | Sele...
Selenium Tutorial For Beginners | Selenium Automation Testing Tutorial | Sele...
Simplilearn
 

Was ist angesagt? (20)

Selenium- A Software Testing Tool
Selenium- A Software Testing ToolSelenium- A Software Testing Tool
Selenium- A Software Testing Tool
 
Introduction to Selenium Web Driver
Introduction to Selenium Web DriverIntroduction to Selenium Web Driver
Introduction to Selenium Web Driver
 
Reactjs
ReactjsReactjs
Reactjs
 
BDD WITH CUCUMBER AND JAVA
BDD WITH CUCUMBER AND JAVABDD WITH CUCUMBER AND JAVA
BDD WITH CUCUMBER AND JAVA
 
Automation - web testing with selenium
Automation - web testing with seleniumAutomation - web testing with selenium
Automation - web testing with selenium
 
Test Automation Framework with BDD and Cucumber
Test Automation Framework with BDD and CucumberTest Automation Framework with BDD and Cucumber
Test Automation Framework with BDD and Cucumber
 
Introduction to jest
Introduction to jestIntroduction to jest
Introduction to jest
 
Test Automation Framework using Cucumber BDD overview (part 1)
Test Automation Framework using Cucumber BDD overview (part 1)Test Automation Framework using Cucumber BDD overview (part 1)
Test Automation Framework using Cucumber BDD overview (part 1)
 
Selenium IDE LOCATORS
Selenium IDE LOCATORSSelenium IDE LOCATORS
Selenium IDE LOCATORS
 
Introduction to React
Introduction to ReactIntroduction to React
Introduction to React
 
Selenium ppt
Selenium pptSelenium ppt
Selenium ppt
 
Web automation using selenium.ppt
Web automation using selenium.pptWeb automation using selenium.ppt
Web automation using selenium.ppt
 
Selenium Interview Questions and Answers | Selenium Tutorial | Selenium Train...
Selenium Interview Questions and Answers | Selenium Tutorial | Selenium Train...Selenium Interview Questions and Answers | Selenium Tutorial | Selenium Train...
Selenium Interview Questions and Answers | Selenium Tutorial | Selenium Train...
 
Using Postman to Automate API On-Boarding
Using Postman to Automate API On-BoardingUsing Postman to Automate API On-Boarding
Using Postman to Automate API On-Boarding
 
Bdd – with cucumber and gherkin
Bdd – with cucumber and gherkinBdd – with cucumber and gherkin
Bdd – with cucumber and gherkin
 
Test automation using selenium
Test automation using seleniumTest automation using selenium
Test automation using selenium
 
Cucumber BDD
Cucumber BDDCucumber BDD
Cucumber BDD
 
Selenium Tutorial For Beginners | Selenium Automation Testing Tutorial | Sele...
Selenium Tutorial For Beginners | Selenium Automation Testing Tutorial | Sele...Selenium Tutorial For Beginners | Selenium Automation Testing Tutorial | Sele...
Selenium Tutorial For Beginners | Selenium Automation Testing Tutorial | Sele...
 
Clean architecture with ddd layering in php
Clean architecture with ddd layering in phpClean architecture with ddd layering in php
Clean architecture with ddd layering in php
 
Create an architecture for web test automation
Create an architecture for web test automationCreate an architecture for web test automation
Create an architecture for web test automation
 

Andere mochten auch

Andere mochten auch (17)

Refactoring page objects The Screenplay Pattern
Refactoring page objects   The Screenplay Pattern Refactoring page objects   The Screenplay Pattern
Refactoring page objects The Screenplay Pattern
 
ScreenPlay Design Patterns for QA Automation
ScreenPlay Design Patterns for QA AutomationScreenPlay Design Patterns for QA Automation
ScreenPlay Design Patterns for QA Automation
 
Beyond Page Objects
Beyond Page ObjectsBeyond Page Objects
Beyond Page Objects
 
Using The Page Object Pattern
Using The Page Object PatternUsing The Page Object Pattern
Using The Page Object Pattern
 
Page Objects Done Right - selenium conference 2014
Page Objects Done Right - selenium conference 2014Page Objects Done Right - selenium conference 2014
Page Objects Done Right - selenium conference 2014
 
Perils of Page-Object Pattern
Perils of Page-Object PatternPerils of Page-Object Pattern
Perils of Page-Object Pattern
 
APIs: A Better Alternative to Page Objects
APIs: A Better Alternative to Page ObjectsAPIs: A Better Alternative to Page Objects
APIs: A Better Alternative to Page Objects
 
Advanced visual testing of web and mobile applications
Advanced visual testing of web and mobile applicationsAdvanced visual testing of web and mobile applications
Advanced visual testing of web and mobile applications
 
CukeUp 2016 Agile Product Planning Workshop
CukeUp 2016 Agile Product Planning WorkshopCukeUp 2016 Agile Product Planning Workshop
CukeUp 2016 Agile Product Planning Workshop
 
DSL, Page Object and WebDriver – the path to reliable functional tests.pptx
DSL, Page Object and WebDriver – the path to reliable functional tests.pptxDSL, Page Object and WebDriver – the path to reliable functional tests.pptx
DSL, Page Object and WebDriver – the path to reliable functional tests.pptx
 
Out of box page object design pattern, java
Out of box page object design pattern, javaOut of box page object design pattern, java
Out of box page object design pattern, java
 
Better Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component PatternBetter Page Object Handling with Loadable Component Pattern
Better Page Object Handling with Loadable Component Pattern
 
BDD Anti-patterns
BDD Anti-patternsBDD Anti-patterns
BDD Anti-patterns
 
Webium: Page Objects In Python (Eng)
Webium: Page Objects In Python (Eng)Webium: Page Objects In Python (Eng)
Webium: Page Objects In Python (Eng)
 
DSL, Page Object and Selenium – a way to reliable functional tests
DSL, Page Object and Selenium – a way to reliable functional testsDSL, Page Object and Selenium – a way to reliable functional tests
DSL, Page Object and Selenium – a way to reliable functional tests
 
Node.js and Selenium Webdriver, a journey from the Java side
Node.js and Selenium Webdriver, a journey from the Java sideNode.js and Selenium Webdriver, a journey from the Java side
Node.js and Selenium Webdriver, a journey from the Java side
 
User Story Mapping, Discover the whole story
User Story Mapping, Discover the whole storyUser Story Mapping, Discover the whole story
User Story Mapping, Discover the whole story
 

Ähnlich wie A journey beyond the page object pattern

Top100summit 谷歌-scott-improve your automated web application testing
Top100summit  谷歌-scott-improve your automated web application testingTop100summit  谷歌-scott-improve your automated web application testing
Top100summit 谷歌-scott-improve your automated web application testing
drewz lin
 
UI Testing Automation
UI Testing AutomationUI Testing Automation
UI Testing Automation
AgileEngine
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e big
Andy Peterson
 
Selenium withnet
Selenium withnetSelenium withnet
Selenium withnet
Vlad Maniak
 

Ähnlich wie A journey beyond the page object pattern (20)

Gems Of Selenium
Gems Of SeleniumGems Of Selenium
Gems Of Selenium
 
Lotusphere 2012 Speedgeeking - jQuery & Domino, a RAD Combination
Lotusphere 2012 Speedgeeking - jQuery & Domino, a RAD CombinationLotusphere 2012 Speedgeeking - jQuery & Domino, a RAD Combination
Lotusphere 2012 Speedgeeking - jQuery & Domino, a RAD Combination
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NET
 
Automation Abstraction Layers: Page Objects and Beyond
Automation Abstraction Layers: Page Objects and BeyondAutomation Abstraction Layers: Page Objects and Beyond
Automation Abstraction Layers: Page Objects and Beyond
 
Improving Your Selenium WebDriver Tests - Belgium testing days_2016
Improving Your Selenium WebDriver Tests - Belgium testing days_2016Improving Your Selenium WebDriver Tests - Belgium testing days_2016
Improving Your Selenium WebDriver Tests - Belgium testing days_2016
 
Top100summit 谷歌-scott-improve your automated web application testing
Top100summit  谷歌-scott-improve your automated web application testingTop100summit  谷歌-scott-improve your automated web application testing
Top100summit 谷歌-scott-improve your automated web application testing
 
Protractor Tutorial Quality in Agile 2015
Protractor Tutorial Quality in Agile 2015Protractor Tutorial Quality in Agile 2015
Protractor Tutorial Quality in Agile 2015
 
Ultimate Introduction To AngularJS
Ultimate Introduction To AngularJSUltimate Introduction To AngularJS
Ultimate Introduction To AngularJS
 
UI Testing Automation
UI Testing AutomationUI Testing Automation
UI Testing Automation
 
Javascript unit testing, yes we can e big
Javascript unit testing, yes we can   e bigJavascript unit testing, yes we can   e big
Javascript unit testing, yes we can e big
 
Choosing a Javascript Framework
Choosing a Javascript FrameworkChoosing a Javascript Framework
Choosing a Javascript Framework
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 
Testing in AngularJS
Testing in AngularJSTesting in AngularJS
Testing in AngularJS
 
Selenium withnet
Selenium withnetSelenium withnet
Selenium withnet
 
Kakunin E2E framework showcase
Kakunin E2E framework showcaseKakunin E2E framework showcase
Kakunin E2E framework showcase
 
An Introduction to AngularJS End to End Testing using Protractor
An Introduction to AngularJS End to End Testing using ProtractorAn Introduction to AngularJS End to End Testing using Protractor
An Introduction to AngularJS End to End Testing using Protractor
 
BDD, ATDD, Page Objects: The Road to Sustainable Web Testing
BDD, ATDD, Page Objects: The Road to Sustainable Web TestingBDD, ATDD, Page Objects: The Road to Sustainable Web Testing
BDD, ATDD, Page Objects: The Road to Sustainable Web Testing
 
UI Testing Automation - Alex Kalinovsky - CreamTec LLC
UI Testing Automation - Alex Kalinovsky - CreamTec LLCUI Testing Automation - Alex Kalinovsky - CreamTec LLC
UI Testing Automation - Alex Kalinovsky - CreamTec LLC
 
Building React Applications with Redux
Building React Applications with ReduxBuilding React Applications with Redux
Building React Applications with Redux
 
Wix Automation - Core
Wix Automation - CoreWix Automation - Core
Wix Automation - Core
 

Kürzlich hochgeladen

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Kürzlich hochgeladen (20)

Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Cyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdfCyberprint. Dark Pink Apt Group [EN].pdf
Cyberprint. Dark Pink Apt Group [EN].pdf
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 

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
  • 7.
  • 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!

Hinweis der Redaktion

  1. New requirement for automated testing -> tests focused on UI -> inverted test pyramid
  2. 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 ...
  3. 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.
  4. Let's talk about testing the PetClinic, a sample Spring application that demonstrates the basic of using the Spring framework.
  5. We have some people with WebDriver experience here. So guys, what is this test trying to prove?
  6. 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
  7. 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?