SlideShare a Scribd company logo
1 of 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!

More Related Content

What's hot

今更聞けない? Androidのテストのいろは
今更聞けない? Androidのテストのいろは今更聞けない? Androidのテストのいろは
今更聞けない? AndroidのテストのいろはHiroshi Kikuchi
 
Introduction to Spring Boot!
Introduction to Spring Boot!Introduction to Spring Boot!
Introduction to Spring Boot!Jakub Kubrynski
 
Graal and Truffle: One VM to Rule Them All
Graal and Truffle: One VM to Rule Them AllGraal and Truffle: One VM to Rule Them All
Graal and Truffle: One VM to Rule Them AllThomas Wuerthinger
 
Advanced javascript
Advanced javascriptAdvanced javascript
Advanced javascriptDoeun KOCH
 
Object Oriented Programming In JavaScript
Object Oriented Programming In JavaScriptObject Oriented Programming In JavaScript
Object Oriented Programming In JavaScriptForziatech
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scalapramode_ce
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with MockitoRichard Paul
 
iFunEngine: 30분 만에 게임 서버 만들기
iFunEngine: 30분 만에 게임 서버 만들기iFunEngine: 30분 만에 게임 서버 만들기
iFunEngine: 30분 만에 게임 서버 만들기iFunFactory Inc.
 
Unit Testing with Jest
Unit Testing with JestUnit Testing with Jest
Unit Testing with JestMaayan Glikser
 
Getting Started with NgRx (Redux) Angular
Getting Started with NgRx (Redux) AngularGetting Started with NgRx (Redux) Angular
Getting Started with NgRx (Redux) AngularGustavo Costa
 
Practical non blocking microservices in java 8
Practical non blocking microservices in java 8Practical non blocking microservices in java 8
Practical non blocking microservices in java 8Michal Balinski
 
jQuery Tutorial For Beginners | Developing User Interface (UI) Using jQuery |...
jQuery Tutorial For Beginners | Developing User Interface (UI) Using jQuery |...jQuery Tutorial For Beginners | Developing User Interface (UI) Using jQuery |...
jQuery Tutorial For Beginners | Developing User Interface (UI) Using jQuery |...Edureka!
 
introduction to Vue.js 3
introduction to Vue.js 3 introduction to Vue.js 3
introduction to Vue.js 3 ArezooKmn
 
SymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdfSymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdfŁukasz Chruściel
 
types of events in JS
types of events in JS types of events in JS
types of events in JS chauhankapil
 
Lessons Learned from Building 100+ C++/Qt/QML Devices
Lessons Learned from Building 100+ C++/Qt/QML DevicesLessons Learned from Building 100+ C++/Qt/QML Devices
Lessons Learned from Building 100+ C++/Qt/QML DevicesICS
 
PostgreSQL Database Slides
PostgreSQL Database SlidesPostgreSQL Database Slides
PostgreSQL Database Slidesmetsarin
 
Mastering Oracle ADF Bindings
Mastering Oracle ADF BindingsMastering Oracle ADF Bindings
Mastering Oracle ADF BindingsEuegene Fedorenko
 

What's hot (20)

今更聞けない? Androidのテストのいろは
今更聞けない? Androidのテストのいろは今更聞けない? Androidのテストのいろは
今更聞けない? Androidのテストのいろは
 
Introduction to Spring Boot!
Introduction to Spring Boot!Introduction to Spring Boot!
Introduction to Spring Boot!
 
Graal and Truffle: One VM to Rule Them All
Graal and Truffle: One VM to Rule Them AllGraal and Truffle: One VM to Rule Them All
Graal and Truffle: One VM to Rule Them All
 
Advanced javascript
Advanced javascriptAdvanced javascript
Advanced javascript
 
Object Oriented Programming In JavaScript
Object Oriented Programming In JavaScriptObject Oriented Programming In JavaScript
Object Oriented Programming In JavaScript
 
Introduction to Functional Programming with Scala
Introduction to Functional Programming with ScalaIntroduction to Functional Programming with Scala
Introduction to Functional Programming with Scala
 
Mocking in Java with Mockito
Mocking in Java with MockitoMocking in Java with Mockito
Mocking in Java with Mockito
 
iFunEngine: 30분 만에 게임 서버 만들기
iFunEngine: 30분 만에 게임 서버 만들기iFunEngine: 30분 만에 게임 서버 만들기
iFunEngine: 30분 만에 게임 서버 만들기
 
Unit Testing with Jest
Unit Testing with JestUnit Testing with Jest
Unit Testing with Jest
 
Getting Started with NgRx (Redux) Angular
Getting Started with NgRx (Redux) AngularGetting Started with NgRx (Redux) Angular
Getting Started with NgRx (Redux) Angular
 
Practical non blocking microservices in java 8
Practical non blocking microservices in java 8Practical non blocking microservices in java 8
Practical non blocking microservices in java 8
 
jQuery Tutorial For Beginners | Developing User Interface (UI) Using jQuery |...
jQuery Tutorial For Beginners | Developing User Interface (UI) Using jQuery |...jQuery Tutorial For Beginners | Developing User Interface (UI) Using jQuery |...
jQuery Tutorial For Beginners | Developing User Interface (UI) Using jQuery |...
 
Memento pattern
Memento patternMemento pattern
Memento pattern
 
introduction to Vue.js 3
introduction to Vue.js 3 introduction to Vue.js 3
introduction to Vue.js 3
 
SymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdfSymfonyCon - Dilemmas and decisions..pdf
SymfonyCon - Dilemmas and decisions..pdf
 
Jest
JestJest
Jest
 
types of events in JS
types of events in JS types of events in JS
types of events in JS
 
Lessons Learned from Building 100+ C++/Qt/QML Devices
Lessons Learned from Building 100+ C++/Qt/QML DevicesLessons Learned from Building 100+ C++/Qt/QML Devices
Lessons Learned from Building 100+ C++/Qt/QML Devices
 
PostgreSQL Database Slides
PostgreSQL Database SlidesPostgreSQL Database Slides
PostgreSQL Database Slides
 
Mastering Oracle ADF Bindings
Mastering Oracle ADF BindingsMastering Oracle ADF Bindings
Mastering Oracle ADF Bindings
 

Viewers also liked

Refactoring page objects The Screenplay Pattern
Refactoring page objects   The Screenplay Pattern Refactoring page objects   The Screenplay Pattern
Refactoring page objects The Screenplay Pattern RiverGlide
 
ScreenPlay Design Patterns for QA Automation
ScreenPlay Design Patterns for QA AutomationScreenPlay Design Patterns for QA Automation
ScreenPlay Design Patterns for QA AutomationCOMAQA.BY
 
Using The Page Object Pattern
Using The Page Object PatternUsing The Page Object Pattern
Using The Page Object PatternDante Briones
 
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 2014Oren Rubin
 
Perils of Page-Object Pattern
Perils of Page-Object PatternPerils of Page-Object Pattern
Perils of Page-Object PatternAnand Bagmar
 
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 ObjectsSauce Labs
 
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 applicationsDenys Zaiats
 
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.pptxMikalai Alimenkou
 
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, javaCOMAQA.BY
 
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 PatternSargis Sargsyan
 
Webium: Page Objects In Python (Eng)
Webium: Page Objects In Python (Eng)Webium: Page Objects In Python (Eng)
Webium: Page Objects In Python (Eng)Uladzimir Franskevich
 
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 testsMikalai Alimenkou
 
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 sideMek Srunyu Stittri
 
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 storyJeff Patton
 

Viewers also liked (18)

Serenity and the Journey Pattern
Serenity and the Journey PatternSerenity and the Journey Pattern
Serenity and the Journey Pattern
 
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
 

Similar to A journey beyond the page object pattern

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 CombinationSean Burgess
 
Testing ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETTesting ASP.NET - Progressive.NET
Testing ASP.NET - Progressive.NETBen Hall
 
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 BeyondAlan Richardson
 
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_2016Roy de Kleijn
 
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 testingdrewz lin
 
Protractor Tutorial Quality in Agile 2015
Protractor Tutorial Quality in Agile 2015Protractor Tutorial Quality in Agile 2015
Protractor Tutorial Quality in Agile 2015Andrew Eisenberg
 
Ultimate Introduction To AngularJS
Ultimate Introduction To AngularJSUltimate Introduction To AngularJS
Ultimate Introduction To AngularJSJacopo Nardiello
 
UI Testing Automation
UI Testing AutomationUI Testing Automation
UI Testing AutomationAgileEngine
 
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 bigAndy Peterson
 
Choosing a Javascript Framework
Choosing a Javascript FrameworkChoosing a Javascript Framework
Choosing a Javascript FrameworkAll Things Open
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenerytoddbr
 
Testing in AngularJS
Testing in AngularJSTesting in AngularJS
Testing in AngularJSPeter Drinnan
 
Selenium withnet
Selenium withnetSelenium withnet
Selenium withnetVlad Maniak
 
Kakunin E2E framework showcase
Kakunin E2E framework showcaseKakunin E2E framework showcase
Kakunin E2E framework showcaseThe Software House
 
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 ProtractorCubet Techno Labs
 
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 TestingJohn Ferguson Smart Limited
 
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 LLCJim Lane
 
Building React Applications with Redux
Building React Applications with ReduxBuilding React Applications with Redux
Building React Applications with ReduxFITC
 
Wix Automation - Core
Wix Automation - CoreWix Automation - Core
Wix Automation - CoreEfrat Attas
 

Similar to 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
 

Recently uploaded

AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAnitaRaj43
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
 
Navigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseNavigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseWSO2
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
API Governance and Monetization - The evolution of API governance
API Governance and Monetization -  The evolution of API governanceAPI Governance and Monetization -  The evolution of API governance
API Governance and Monetization - The evolution of API governanceWSO2
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDropbox
 
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...DianaGray10
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard37
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaWSO2
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontologyjohnbeverley2021
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
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 Takeoffsammart93
 
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.pdfOrbitshub
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
 
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....rightmanforbloodline
 
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 FMESafe Software
 
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)Samir Dash
 
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 AmsterdamUiPathCommunity
 

Recently uploaded (20)

AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
Navigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern EnterpriseNavigating Identity and Access Management in the Modern Enterprise
Navigating Identity and Access Management in the Modern Enterprise
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
API Governance and Monetization - The evolution of API governance
API Governance and Monetization -  The evolution of API governanceAPI Governance and Monetization -  The evolution of API governance
API Governance and Monetization - The evolution of API governance
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
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...
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using Ballerina
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
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
 
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
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
 
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
 
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
WSO2 Micro Integrator for Enterprise Integration in a Decentralized, Microser...
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
 
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
 

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!

Editor's Notes

  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?