SlideShare a Scribd company logo
BDD, ATDD, Page Objects
          The Road to Sustainable Web Testing




John Ferguson Smart
So who is this guy, anyway?
               Consulta
                       nt
               Trainer
              Mentor
              Author
             Speaker
             Coder
   John Fer
            guson S
                    mar t
Java Power Tools Bootcamp at Skills Matter
           ALL YOUR AGILE JAVA TOOLS
           TRAINING ARE BELONG TO US
                          bDr iver
                m	
  2/We
mave     Seleniu        Hudson
    n
                                  BDD
             JUnit
TD
     D

                                London
                           January 24-28 2011
Don’t let your web tests end up like this!
The Three Ways of Automated Web Testing




        Record/Replay

      Scripting

Page Objects
Record-replay automated tests




      Promise           Reality
Record-replay automated tests
Script-based automated tests

Selenium RC

      HTMLUnit

              JWebUnit

                     Canoe Webtest

                               Watir
Script-based automated tests

Selenium RC

      HTMLUnit

              JWebUnit

                     Canoe Webtest

                               Watir
What we’d like to have...
                     D.R.Y
      Don’t Repeat Yourself
What we’d like to have...




   Reusable building blocks
What we’d like to have...




A communication tool
Introducing Page Objects

Reusable


 Low
 maintenance


  Speak your language
Page Objects




          are reusable components
Page Objects




          hide unnecessary details
Page Objects




               are low maintenance
Page Objects




        speak everybody’s language
Page Objects in action




            An example
Page Objects in action
The old way - Selenium RC
 selenium = new DefaultSelenium("localhost", 4444, "*firefox", "http://www.google.com/");

 selenium.open("http://www.google.com");
 selenium.waitForPageToLoad(5000);

 selenium.type("q", "cats");
 selenium.click("BtnG");
 selenium.waitForPageToLoad(5000);

 assertThat(selenium.isTextPresent("cats"), is(true));
Page Objects in action
The new way - Using Page Objects
 WebDriver driver = new FirefoxDriver();
 GoogleSearchPage page = new GoogleSearchPage(driver);

 page.open();
 page.searchFor("cats");

 assertThat(page.getTitle(), containsString("cats") );

 page.close();
Page Objects in action
The new way - Using Page Objects
 WebDriver driver = new FirefoxDriver();
 GoogleSearchPage page = new GoogleSearchPage(driver);

 page.open();
 page.searchFor("cats");

 assertThat(page.getTitle(), containsString("cats") );

 page.close();
                                                         GoogleSearchPage

                                                     open()
                                                     close()
                                                     searchFor( query : String )
                                                     clickOnFeelingLucky()
                                                     openAdvancedSearchOptions()
                                                     ...
Page Objects in action
The new way - another example




                    WebDriver driver = new FirefoxDriver();
                    GoogleSearchPage page = new GoogleSearchPage(driver);
    Hides HTML
                    page.open()
          details   page.typeIntoSearchBox("cats");
                    List<String> suggestions = page.getSuggestions();
        Uses
                    assertThat(suggestions, hasItem("cats and dogs"));
     business
       terms        page.close();
From Pages Objects to BDD




Taking expressive tests
to the next level
BDD in action
WebDriver driver = new FirefoxDriver();
GoogleSearchPage page = new GoogleSearchPage(driver);

page.open()
page.typeIntoSearchBox("cats");
List<String> suggestions = page.getSuggestions();

assertThat(suggestions, hasItem("cats and dogs"));

page.close();




But would your testers
      understand this?
BDD in action                                                         Much more
                                                                        readable

using "google-search"

scenario "Searching for 'cats' on Google", {
	

 when "the user types 'cats' in the search box", {
	

 	

 onTheWebPage.typeIntoSearchBox "cats"
	

 }
	

 then "the drop-down suggestions should include 'cats and dogs'"
	

 	

 theWebPage.suggestions.shouldHave "cats and dogs"
	

 }
}




                        Still uses Page Objects
                                under the hood
                                                         How about this?
BDD in action




                More readable
                    reporting
So how does it work?
                   Easyb Plugin
using "google-search"

scenario "Searching for 'cats' on Google",{
	

 when "the user types 'cats' in the search box", {
	

 	

 onTheWebPage.typeIntoSearchBox "cats"
	

 }
	

 then "the drop-down suggestions should include 'cats and dogs'"
	

 	

 theWebPage.suggestions.shouldHave "cats and dogs"
	

 }
}
                                                                          Page Objects




                                                                      Page Navigation
Automated Acceptance Tests




      Where are your goal posts?
Automated Acceptance Tests




   Unit tests are for   Acceptance tests are
      developers          for everyone else
Automated Acceptance Tests




   Unit tests are for   Acceptance tests are
      developers          for everyone else
Automated Acceptance Tests
                                  Passing
                                acceptance
                                   tests




                              Pending
                             acceptance
                                tests
Automated Acceptance Tests

                     Acceptance
                        tests




                              Pending
                             acceptance
                                tests
Automated Acceptance Tests
tags ["acceptance", "sprint-1"]                            Implement these in
scenario "An empty grid should produce an empty grid",{
                                                                Sprint 1
	 when "the user chooses to start a new game", {
	 	 newGamePage = homePage.clickOnNewGameLink()
	 }
	 then "the user is invited to enter the initial state of the universe", {
	 	 newGamePage.text.shouldHave "Please seed your universe"	 	 	 	
	 }
}

scenario "The user can seed the universe with an initial grid",{
	 given "the user is on the new grid page", {
	 	 newGridPage = homePage.clickOnNewGameLink()
	 }
	 when "that the user clicks on Go without picking any cells", {
        gridDisplayPage = newGridPage.clickOnGoButton()
	 }
	 then "the application will display an empty universe", {
	 	 String[][] anEmptyGrid = [[".", ".", "."],
	 	                              [".", ".", "."],
	 	 	 	 	                        [".", ".", "."]]
	 	 gridDisplayPage.displayedGrid.shouldBe anEmptyGrid
	 }
}
And now for
the case studies
Case Study




   Government online form processing
Architecture - fitting it all together


      Acceptance tests

              Easyb Plugin


            Page Objects



                  Integration
                     tests      JUnit

        Web Application
The application
                  Perl and Java



                    Lots of forms



                       Ugly colours
What the tester uses
using "ecert"                                      Custom easyb plugin
tags "TC02"
                                                              Plugin handles
before "we are connected to the UAT environment", {
                                                              authentication
	 given "we are connected to the UAT environment", {
	 	 connecting.to('uat').withUser('a_tester')
	 }
}                                                            Business-level tests
scenario "The user opens the 'New Export Certificate' page and selects a country",{
	 when "the user clicks on the 'New Export Certificate' menu", {
	 	 onTheWebPage.navigationPanel.clickOnNewExportCertificate()	 	
	 }
	 and "the user chooses USA and clicks on 'Show Data Entry'", {
	 	 onTheWebPage.selectDeclarationFormFor 'United States'	  	
	 }
	 then "we should be on the US Export Certification Preparation page", {
	 	 theWebPage.asText.shouldHave "Export Certificate Preparation"	 	
	 	 theWebPage.asText.shouldHave "Declarations for United States"	 	
	 }
	 and "the 'Raise New Blank Export Certificate' is default and selected", {
	 	 theWebPage.raiseNewBlankCertificate.shouldBeSelected()
	 }
}
More nice screens
What the tester uses
...
scenario "The user fills in the Export Certificate Submission Form",{
	 when "we fill in the export certificate details", {
	 	 theWebPage.with {
	 	       certificateNumber = '123456'
	 	 	 consignor = 'LANEXCO1'
	 	 	 importerID = '123'                                 Groovy shortcuts
	 	 	 importerName = 'ImportsRUs'
	 	 	 importerRepresentative = 'local guy'
	 	 	 officialInformation = 'very important'
	 	 	 transportMode = 'AIR'
	 	 	 carrierName = 'AirNZ'                               Business-level tests
	 	 	 productItem(1).description = 'Product data'
	 	 	 productItem(1).harmonizedSystemCode = '020110'
	 	 	 productItem(1).with {
	 	 	 	 process(1).with {
	 	 	 	 	 type = 'Freezing'
	 	 	 	 	 processingStartDate = '01/01/2010'                      Handling
	 	 	 	 	 processingEndDate = '02/01/2010'                      nested forms
	 	 	 	 	 appliedBy = 'some dude'	      	 	
	 	 	 	 	 overrideSelected()
	 	 	 	 }
           ...
What the Page Objects look like
public class ECertNavigationPanel extends AuthenticatedWebPage {

	       @FindBy(linkText="XML Submit")
	       WebElement xmlSubmit;
	                                                           WebDriver annotations
	       @FindBy(linkText="New Export Certificate")
	       WebElement newExportCertificate;

	       public ECertNavigationPanel(WebDriver driver) {
	       	   super(driver);
	       }
	       	   	
	       public WebElement getXmlSubmit() {...}

	       public WebElement getNewExportCertificate() {...}

    	   public ECertSubmitXmlPage clickOnXmlSubmit() {...}
	
	       public ExportCertificatePreparationPage clickOnNewExportCertificate() {...}	
	
	
}
Case Study




      Class Report
   An online reporting
      tool for lawyers
          h"p://customfirst.com
Architecture - fitting it all together


          Regression/
       Integration tests




             Page Objects




         Web Application
The application
                  RUI Application




                     Lots of AJAX
                              !
What the tests look like
@Mixin (SeleniumTest)
class ReportViewerTests extends AbstractSeleniumBaseTest
{
    ViewerPage viewerPage
                                                              Setting up the
	
	
    public void setUp() {
        super.setUp()
                                                               Page Object
	   	   TestFixtures.loadData()
         viewerPage = new ViewerPage(selenium, contextPath)
	   	   viewerPage.openHomePage()
    }

	   public void testClickingGLReportsIconShouldDisplaySubFolders() {
	       viewerPage.clickFolderOpenIcon("GL Reports")
	       assertTrue viewerPage.folderPresent("Accounts")                Testing the app
	       assertTrue viewerPage.folderPresent("Test Reports")
    }

    public void testClickingOnASubFolderShouldDisplayReports() {
	   	   viewerPage.clickFolderOpenIcon("GL Reports")
	   	   assertTrue viewerPage.folderPresent("Test Reports")
	       viewerPage.clickFolder "Test Reports"
	   	   assertTrue viewerPage.reportRowPresent("Test Reports","Aged Debtors By Client")
	   	   assertTrue viewerPage.reportRowPresent("Test Reports","Chart")
    }
	   ...
What the Page Objects look like
class ViewerPage   extends AbstractPageObject{

  public ViewerPage(def selenium, def contextPath) {           Business-friendly
    super(selenium, contextPath)
  }                                                                methods
  public void clickFolder(String folderName) {...}

  public void clickFolderOpenIcon(String folderId) {...}	

  public boolean   folderPresent(String folderName){...}

  public boolean reportRowPresent(String folder,String rowName){...}

  public boolean reportParameterPresent(String reportName,String parameterName){...}

  public boolean reportRowTextPresent(String folder,String reportName,String text){...}
  ...
Case Study




Financial software
The application
                  Looks a bit like
                    this one...
                    (but more complex)

                          (and top secret)

                               (Shhhhhh!)




                               Again, lots of AJAX
                                                !
Page Components
                                                              Reusable component
class RadioButton {
    WebElement button
    WebElement buttonContainer;
    def buttonId
    def driver

    void clickButton() {
        initButton()
        button.click();
    }

    void shouldBeEnabled() {
        assert !isDisabled();
    }

    void shouldBeDisabled() {
        assert isDisabled();
    }                                                       Horrible nasty GWT code
    private boolean isDisabled() {
        initButton()
        return buttonContainer.getAttribute("class").contains("x-item-disabled");
    }

    private void initButton()
    {
        if (button==null) {
            buttonContainer=driver.findElement(By.id("gwt-debug-${buttonId}_BUTTON"));
            button=driver.findElement(By.xpath("//input[contains(@value, ${buttonId}-input)]"));
        }
    }
}
Page Components
 @Test
 public void userShouldBecomeOwnerOfCurrentWorkItem() {
     page.workItemTree.selectEntryCalled("Stuff to do")
     ...
     page.assignButton.shouldBeEnabled()
     page.assignButton.click();                    Click on a button
     page.assignButton.shouldBeHidden();
     page.retryButton.shouldBeEnabled();
     page.saveButton.shouldBeDisabled()
     page.saveButton.shouldBePresent();               Custom asserts
 }

       scenario "No work items should initially appear on the screen",{
           when "the user opens the page", {
               page.open()
           }
           and "the Item Tree 'Show all' check box should not be ticked", {
               assert page.itemTree.showAll.isNotChecked()
           }
           and "the Item Tree should contain no work items", {
               assert page.itemTree.isEmpty()
           }
       }                                                  BDD-style tests
Page Components
class Grid {
                                            A Grid (table) component
    def driver
    def gridId

    def getAt(int i) {                               It looks like an array
        def gridRows = getGridRows()
        return gridRows[i]
    }

    def size() {
        def gridRows = getGridRows()
        return gridRows.size()
    }

    def shouldHaveARowWith(def map) {
        def gridRows = getGridRows()

        def matchingRowFound = true

        for(entry in map) {
            def gridRow = gridRows.find { row ->
                row[entry.key] == entry.value
            }

               matchingRowFound = gridRow != null
        }

        return matchingRowFound
    }
Page Components
 @Test
 void theSummaryItemChangesToReflectTreeChoice() {
     page.itemTree.selectEntryCalled("Stuff to do")       This is not an array
     assert page.itemSummaryGrid.size() == 1

     def highlightedItemSummaryRow = page.itemSummaryGrid[0]
     assert highlightedItemSummaryRow.customerName == "ACME Inc"
 }
ATDD, BDD and Page Objects
Clean, precise, well-designed




                 Powerful, robust, low-maintenance
                                               John	
  Ferguson	
  Smart
                                Email:	
  john.smart@wakaleo.com
                                 Web:	
  h"p://www.wakaleo.com
                                                   Twi"er:	
  wakaleo

More Related Content

What's hot (19)

PPTX
Realm or: How I learned to stop worrying and love my app database
Sergi Martínez
 
KEY
SOLID Principles
Chris Weldon
 
PDF
JSON and Swift, Still A Better Love Story Than Twilight
Donny Wals
 
PDF
Effiziente Datenpersistierung mit JPA 2.1 und Hibernate
Thorben Janssen
 
PDF
Why realm?
Leonardo Taehwan Kim
 
DOCX
Kode vb.net
Azki Nabidin
 
PPTX
Windows 8 JavaScript (Wonderland)
Christopher Bennage
 
PDF
InheritedWidget is your friend - GDG London (2018-08-08)
Andrea Bizzotto
 
PPTX
Testable, Object-Oriented JavaScript
Jon Kruger
 
PDF
Vaadin7
Joonas Lehtinen
 
PDF
Di and Dagger
K. Matthew Dupree
 
PDF
JavaEE 8 on a diet with Payara Micro 5
Payara
 
PPT
Air Drag And Drop
michael.labriola
 
PPTX
Final microsoft cloud summit - windows azure building block services
stratospheres
 
PPTX
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Jon Kruger
 
PPTX
13 networking, mobile services, and authentication
WindowsPhoneRocks
 
PDF
Di web tech mail (no subject)
shubhamvcs
 
PPT
Diving in the Flex Data Binding Waters
michael.labriola
 
PPTX
J Query Presentation of David
Arun David Johnson R
 
Realm or: How I learned to stop worrying and love my app database
Sergi Martínez
 
SOLID Principles
Chris Weldon
 
JSON and Swift, Still A Better Love Story Than Twilight
Donny Wals
 
Effiziente Datenpersistierung mit JPA 2.1 und Hibernate
Thorben Janssen
 
Kode vb.net
Azki Nabidin
 
Windows 8 JavaScript (Wonderland)
Christopher Bennage
 
InheritedWidget is your friend - GDG London (2018-08-08)
Andrea Bizzotto
 
Testable, Object-Oriented JavaScript
Jon Kruger
 
Di and Dagger
K. Matthew Dupree
 
JavaEE 8 on a diet with Payara Micro 5
Payara
 
Air Drag And Drop
michael.labriola
 
Final microsoft cloud summit - windows azure building block services
stratospheres
 
Venturing Into The Wild: A .NET Developer's Experience As A Ruby Developer
Jon Kruger
 
13 networking, mobile services, and authentication
WindowsPhoneRocks
 
Di web tech mail (no subject)
shubhamvcs
 
Diving in the Flex Data Binding Waters
michael.labriola
 
J Query Presentation of David
Arun David Johnson R
 

Similar to BDD, ATDD, Page Objects: The Road to Sustainable Web Testing (20)

PPTX
DSL, Page Object and WebDriver – the path to reliable functional tests.pptx
Mikalai Alimenkou
 
PPTX
DSL, Page Object и WebDriver – путь к надежным функциональным тестам
SQALab
 
PDF
Acceptance Testing of Web UI
Vladimir Tsukur
 
PDF
Ui automation
test test
 
PPT
Test strategy for web development
alice yang
 
PPTX
4&5.pptx SOFTWARE TESTING UNIT-4 AND UNIT-5
hemasubbu08
 
PPT
Test Automation Framework Designs
Sauce Labs
 
PPTX
Automated integration tests for ajax applications (с. карпушин, auriga)
Mobile Developer Day
 
PPT
Test Automation Framework Designs
Test Automaton
 
PPT
selenium.ppt
AmenSheikh
 
PPT
selenium.ppt
ssuser7b4894
 
PPT
selenium.ppt
rajnexient
 
PDF
Does my test script smell?
MartinGijsen
 
PPT
Internal DSLs For Automated Functional Testing
John Sonmez
 
PDF
Tellurium.A.New.Approach.For.Web.Testing
John.Jian.Fang
 
PPTX
Top100summit christina
Christina Geng
 
PDF
Tellurium.A.New.Approach.For.Web.Testing.V5
John.Jian.Fang
 
PPT
Selenium
Sun Technlogies
 
PDF
Testing Experience - Evolution of Test Automation Frameworks
Łukasz Morawski
 
PPTX
Designing for the internet - Page Objects for the Real World
Qualitest
 
DSL, Page Object and WebDriver – the path to reliable functional tests.pptx
Mikalai Alimenkou
 
DSL, Page Object и WebDriver – путь к надежным функциональным тестам
SQALab
 
Acceptance Testing of Web UI
Vladimir Tsukur
 
Ui automation
test test
 
Test strategy for web development
alice yang
 
4&5.pptx SOFTWARE TESTING UNIT-4 AND UNIT-5
hemasubbu08
 
Test Automation Framework Designs
Sauce Labs
 
Automated integration tests for ajax applications (с. карпушин, auriga)
Mobile Developer Day
 
Test Automation Framework Designs
Test Automaton
 
selenium.ppt
AmenSheikh
 
selenium.ppt
ssuser7b4894
 
selenium.ppt
rajnexient
 
Does my test script smell?
MartinGijsen
 
Internal DSLs For Automated Functional Testing
John Sonmez
 
Tellurium.A.New.Approach.For.Web.Testing
John.Jian.Fang
 
Top100summit christina
Christina Geng
 
Tellurium.A.New.Approach.For.Web.Testing.V5
John.Jian.Fang
 
Selenium
Sun Technlogies
 
Testing Experience - Evolution of Test Automation Frameworks
Łukasz Morawski
 
Designing for the internet - Page Objects for the Real World
Qualitest
 
Ad

More from John Ferguson Smart Limited (20)

PPTX
My Reading Specs - Refactoring Patterns for Gherkin Scenarios
John Ferguson Smart Limited
 
PDF
Artisti e Condotierri - How can your team become artists of the 21st century ...
John Ferguson Smart Limited
 
PDF
Engage! Bringing teams together to deliver software that makes a difference
John Ferguson Smart Limited
 
PDF
BE A POD OF DOLPHINS, NOT A DANCING ELEPHANT
John Ferguson Smart Limited
 
PDF
Sustainable Test Automation with Serenity BDD and Screenplay
John Ferguson Smart Limited
 
PDF
Feature Mapping Workshop
John Ferguson Smart Limited
 
PDF
Engage! Bringing teams together to deliver software that makes a difference
John Ferguson Smart Limited
 
PDF
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
John Ferguson Smart Limited
 
PDF
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
John Ferguson Smart Limited
 
PDF
Shift left-devoxx-pl
John Ferguson Smart Limited
 
PDF
Screenplay - Next generation automated acceptance testing
John Ferguson Smart Limited
 
PDF
Cucumber and Spock Primer
John Ferguson Smart Limited
 
PDF
All the world's a stage – the next step in automated testing practices
John Ferguson Smart Limited
 
PDF
CukeUp 2016 Agile Product Planning Workshop
John Ferguson Smart Limited
 
PDF
BDD Anti-patterns
John Ferguson Smart Limited
 
PDF
Serenity and the Journey Pattern
John Ferguson Smart Limited
 
PDF
BDD - Collaborate like you mean it!
John Ferguson Smart Limited
 
PDF
BDD-Driven Microservices
John Ferguson Smart Limited
 
PDF
BDD Anti-patterns
John Ferguson Smart Limited
 
PDF
It's Testing, Jim, but not as we know it - BDD for Testers
John Ferguson Smart Limited
 
My Reading Specs - Refactoring Patterns for Gherkin Scenarios
John Ferguson Smart Limited
 
Artisti e Condotierri - How can your team become artists of the 21st century ...
John Ferguson Smart Limited
 
Engage! Bringing teams together to deliver software that makes a difference
John Ferguson Smart Limited
 
BE A POD OF DOLPHINS, NOT A DANCING ELEPHANT
John Ferguson Smart Limited
 
Sustainable Test Automation with Serenity BDD and Screenplay
John Ferguson Smart Limited
 
Feature Mapping Workshop
John Ferguson Smart Limited
 
Engage! Bringing teams together to deliver software that makes a difference
John Ferguson Smart Limited
 
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
John Ferguson Smart Limited
 
Beyond Given/When/Then - why diving into Cucumber is the wrong approach to ad...
John Ferguson Smart Limited
 
Shift left-devoxx-pl
John Ferguson Smart Limited
 
Screenplay - Next generation automated acceptance testing
John Ferguson Smart Limited
 
Cucumber and Spock Primer
John Ferguson Smart Limited
 
All the world's a stage – the next step in automated testing practices
John Ferguson Smart Limited
 
CukeUp 2016 Agile Product Planning Workshop
John Ferguson Smart Limited
 
BDD Anti-patterns
John Ferguson Smart Limited
 
Serenity and the Journey Pattern
John Ferguson Smart Limited
 
BDD - Collaborate like you mean it!
John Ferguson Smart Limited
 
BDD-Driven Microservices
John Ferguson Smart Limited
 
BDD Anti-patterns
John Ferguson Smart Limited
 
It's Testing, Jim, but not as we know it - BDD for Testers
John Ferguson Smart Limited
 
Ad

Recently uploaded (20)

PDF
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
PDF
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
PDF
Windsurf Meetup Ottawa 2025-07-12 - Planning Mode at Reliza.pdf
Pavel Shukhman
 
PPTX
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
PPTX
✨Unleashing Collaboration: Salesforce Channels & Community Power in Patna!✨
SanjeetMishra29
 
PDF
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
PDF
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PDF
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
PPTX
Top iOS App Development Company in the USA for Innovative Apps
SynapseIndia
 
PDF
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
PDF
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
PDF
SFWelly Summer 25 Release Highlights July 2025
Anna Loughnan Colquhoun
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
PPTX
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PDF
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
Building Real-Time Digital Twins with IBM Maximo & ArcGIS Indoors
Safe Software
 
Windsurf Meetup Ottawa 2025-07-12 - Planning Mode at Reliza.pdf
Pavel Shukhman
 
Q2 FY26 Tableau User Group Leader Quarterly Call
lward7
 
✨Unleashing Collaboration: Salesforce Channels & Community Power in Patna!✨
SanjeetMishra29
 
Reverse Engineering of Security Products: Developing an Advanced Microsoft De...
nwbxhhcyjv
 
Chris Elwell Woburn, MA - Passionate About IT Innovation
Chris Elwell Woburn, MA
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
Top iOS App Development Company in the USA for Innovative Apps
SynapseIndia
 
The Builder’s Playbook - 2025 State of AI Report.pdf
jeroen339954
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
Newgen 2022-Forrester Newgen TEI_13 05 2022-The-Total-Economic-Impact-Newgen-...
darshakparmar
 
SFWelly Summer 25 Release Highlights July 2025
Anna Loughnan Colquhoun
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
"Autonomy of LLM Agents: Current State and Future Prospects", Oles` Petriv
Fwdays
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
Exolore The Essential AI Tools in 2025.pdf
Srinivasan M
 

BDD, ATDD, Page Objects: The Road to Sustainable Web Testing

  • 1. BDD, ATDD, Page Objects The Road to Sustainable Web Testing John Ferguson Smart
  • 2. So who is this guy, anyway? Consulta nt Trainer Mentor Author Speaker Coder John Fer guson S mar t
  • 3. Java Power Tools Bootcamp at Skills Matter ALL YOUR AGILE JAVA TOOLS TRAINING ARE BELONG TO US bDr iver m  2/We mave Seleniu Hudson n BDD JUnit TD D London January 24-28 2011
  • 4. Don’t let your web tests end up like this!
  • 5. The Three Ways of Automated Web Testing Record/Replay Scripting Page Objects
  • 8. Script-based automated tests Selenium RC HTMLUnit JWebUnit Canoe Webtest Watir
  • 9. Script-based automated tests Selenium RC HTMLUnit JWebUnit Canoe Webtest Watir
  • 10. What we’d like to have... D.R.Y Don’t Repeat Yourself
  • 11. What we’d like to have... Reusable building blocks
  • 12. What we’d like to have... A communication tool
  • 13. Introducing Page Objects Reusable Low maintenance Speak your language
  • 14. Page Objects are reusable components
  • 15. Page Objects hide unnecessary details
  • 16. Page Objects are low maintenance
  • 17. Page Objects speak everybody’s language
  • 18. Page Objects in action An example
  • 19. Page Objects in action The old way - Selenium RC selenium = new DefaultSelenium("localhost", 4444, "*firefox", "http://www.google.com/"); selenium.open("http://www.google.com"); selenium.waitForPageToLoad(5000); selenium.type("q", "cats"); selenium.click("BtnG"); selenium.waitForPageToLoad(5000); assertThat(selenium.isTextPresent("cats"), is(true));
  • 20. Page Objects in action The new way - Using Page Objects WebDriver driver = new FirefoxDriver(); GoogleSearchPage page = new GoogleSearchPage(driver); page.open(); page.searchFor("cats"); assertThat(page.getTitle(), containsString("cats") ); page.close();
  • 21. Page Objects in action The new way - Using Page Objects WebDriver driver = new FirefoxDriver(); GoogleSearchPage page = new GoogleSearchPage(driver); page.open(); page.searchFor("cats"); assertThat(page.getTitle(), containsString("cats") ); page.close(); GoogleSearchPage open() close() searchFor( query : String ) clickOnFeelingLucky() openAdvancedSearchOptions() ...
  • 22. Page Objects in action The new way - another example WebDriver driver = new FirefoxDriver(); GoogleSearchPage page = new GoogleSearchPage(driver); Hides HTML page.open() details page.typeIntoSearchBox("cats"); List<String> suggestions = page.getSuggestions(); Uses assertThat(suggestions, hasItem("cats and dogs")); business terms page.close();
  • 23. From Pages Objects to BDD Taking expressive tests to the next level
  • 24. BDD in action WebDriver driver = new FirefoxDriver(); GoogleSearchPage page = new GoogleSearchPage(driver); page.open() page.typeIntoSearchBox("cats"); List<String> suggestions = page.getSuggestions(); assertThat(suggestions, hasItem("cats and dogs")); page.close(); But would your testers understand this?
  • 25. BDD in action Much more readable using "google-search" scenario "Searching for 'cats' on Google", { when "the user types 'cats' in the search box", { onTheWebPage.typeIntoSearchBox "cats" } then "the drop-down suggestions should include 'cats and dogs'" theWebPage.suggestions.shouldHave "cats and dogs" } } Still uses Page Objects under the hood How about this?
  • 26. BDD in action More readable reporting
  • 27. So how does it work? Easyb Plugin using "google-search" scenario "Searching for 'cats' on Google",{ when "the user types 'cats' in the search box", { onTheWebPage.typeIntoSearchBox "cats" } then "the drop-down suggestions should include 'cats and dogs'" theWebPage.suggestions.shouldHave "cats and dogs" } } Page Objects Page Navigation
  • 28. Automated Acceptance Tests Where are your goal posts?
  • 29. Automated Acceptance Tests Unit tests are for Acceptance tests are developers for everyone else
  • 30. Automated Acceptance Tests Unit tests are for Acceptance tests are developers for everyone else
  • 31. Automated Acceptance Tests Passing acceptance tests Pending acceptance tests
  • 32. Automated Acceptance Tests Acceptance tests Pending acceptance tests
  • 33. Automated Acceptance Tests tags ["acceptance", "sprint-1"] Implement these in scenario "An empty grid should produce an empty grid",{ Sprint 1 when "the user chooses to start a new game", { newGamePage = homePage.clickOnNewGameLink() } then "the user is invited to enter the initial state of the universe", { newGamePage.text.shouldHave "Please seed your universe" } } scenario "The user can seed the universe with an initial grid",{ given "the user is on the new grid page", { newGridPage = homePage.clickOnNewGameLink() } when "that the user clicks on Go without picking any cells", { gridDisplayPage = newGridPage.clickOnGoButton() } then "the application will display an empty universe", { String[][] anEmptyGrid = [[".", ".", "."], [".", ".", "."], [".", ".", "."]] gridDisplayPage.displayedGrid.shouldBe anEmptyGrid } }
  • 34. And now for the case studies
  • 35. Case Study Government online form processing
  • 36. Architecture - fitting it all together Acceptance tests Easyb Plugin Page Objects Integration tests JUnit Web Application
  • 37. The application Perl and Java Lots of forms Ugly colours
  • 38. What the tester uses using "ecert" Custom easyb plugin tags "TC02" Plugin handles before "we are connected to the UAT environment", { authentication given "we are connected to the UAT environment", { connecting.to('uat').withUser('a_tester') } } Business-level tests scenario "The user opens the 'New Export Certificate' page and selects a country",{ when "the user clicks on the 'New Export Certificate' menu", { onTheWebPage.navigationPanel.clickOnNewExportCertificate() } and "the user chooses USA and clicks on 'Show Data Entry'", { onTheWebPage.selectDeclarationFormFor 'United States' } then "we should be on the US Export Certification Preparation page", { theWebPage.asText.shouldHave "Export Certificate Preparation" theWebPage.asText.shouldHave "Declarations for United States" } and "the 'Raise New Blank Export Certificate' is default and selected", { theWebPage.raiseNewBlankCertificate.shouldBeSelected() } }
  • 40. What the tester uses ... scenario "The user fills in the Export Certificate Submission Form",{ when "we fill in the export certificate details", { theWebPage.with { certificateNumber = '123456' consignor = 'LANEXCO1' importerID = '123' Groovy shortcuts importerName = 'ImportsRUs' importerRepresentative = 'local guy' officialInformation = 'very important' transportMode = 'AIR' carrierName = 'AirNZ' Business-level tests productItem(1).description = 'Product data' productItem(1).harmonizedSystemCode = '020110' productItem(1).with { process(1).with { type = 'Freezing' processingStartDate = '01/01/2010' Handling processingEndDate = '02/01/2010' nested forms appliedBy = 'some dude' overrideSelected() } ...
  • 41. What the Page Objects look like public class ECertNavigationPanel extends AuthenticatedWebPage { @FindBy(linkText="XML Submit") WebElement xmlSubmit; WebDriver annotations @FindBy(linkText="New Export Certificate") WebElement newExportCertificate; public ECertNavigationPanel(WebDriver driver) { super(driver); } public WebElement getXmlSubmit() {...} public WebElement getNewExportCertificate() {...} public ECertSubmitXmlPage clickOnXmlSubmit() {...} public ExportCertificatePreparationPage clickOnNewExportCertificate() {...} }
  • 42. Case Study Class Report An online reporting tool for lawyers h"p://customfirst.com
  • 43. Architecture - fitting it all together Regression/ Integration tests Page Objects Web Application
  • 44. The application RUI Application Lots of AJAX !
  • 45. What the tests look like @Mixin (SeleniumTest) class ReportViewerTests extends AbstractSeleniumBaseTest { ViewerPage viewerPage Setting up the public void setUp() { super.setUp() Page Object TestFixtures.loadData() viewerPage = new ViewerPage(selenium, contextPath) viewerPage.openHomePage() } public void testClickingGLReportsIconShouldDisplaySubFolders() { viewerPage.clickFolderOpenIcon("GL Reports") assertTrue viewerPage.folderPresent("Accounts") Testing the app assertTrue viewerPage.folderPresent("Test Reports") } public void testClickingOnASubFolderShouldDisplayReports() { viewerPage.clickFolderOpenIcon("GL Reports") assertTrue viewerPage.folderPresent("Test Reports") viewerPage.clickFolder "Test Reports" assertTrue viewerPage.reportRowPresent("Test Reports","Aged Debtors By Client") assertTrue viewerPage.reportRowPresent("Test Reports","Chart") } ...
  • 46. What the Page Objects look like class ViewerPage extends AbstractPageObject{ public ViewerPage(def selenium, def contextPath) { Business-friendly super(selenium, contextPath) } methods public void clickFolder(String folderName) {...} public void clickFolderOpenIcon(String folderId) {...} public boolean folderPresent(String folderName){...} public boolean reportRowPresent(String folder,String rowName){...} public boolean reportParameterPresent(String reportName,String parameterName){...} public boolean reportRowTextPresent(String folder,String reportName,String text){...} ...
  • 48. The application Looks a bit like this one... (but more complex) (and top secret) (Shhhhhh!) Again, lots of AJAX !
  • 49. Page Components Reusable component class RadioButton { WebElement button WebElement buttonContainer; def buttonId def driver void clickButton() { initButton() button.click(); } void shouldBeEnabled() { assert !isDisabled(); } void shouldBeDisabled() { assert isDisabled(); } Horrible nasty GWT code private boolean isDisabled() { initButton() return buttonContainer.getAttribute("class").contains("x-item-disabled"); } private void initButton() { if (button==null) { buttonContainer=driver.findElement(By.id("gwt-debug-${buttonId}_BUTTON")); button=driver.findElement(By.xpath("//input[contains(@value, ${buttonId}-input)]")); } } }
  • 50. Page Components @Test public void userShouldBecomeOwnerOfCurrentWorkItem() { page.workItemTree.selectEntryCalled("Stuff to do") ... page.assignButton.shouldBeEnabled() page.assignButton.click(); Click on a button page.assignButton.shouldBeHidden(); page.retryButton.shouldBeEnabled(); page.saveButton.shouldBeDisabled() page.saveButton.shouldBePresent(); Custom asserts } scenario "No work items should initially appear on the screen",{ when "the user opens the page", { page.open() } and "the Item Tree 'Show all' check box should not be ticked", { assert page.itemTree.showAll.isNotChecked() } and "the Item Tree should contain no work items", { assert page.itemTree.isEmpty() } } BDD-style tests
  • 51. Page Components class Grid { A Grid (table) component def driver def gridId def getAt(int i) { It looks like an array def gridRows = getGridRows() return gridRows[i] } def size() { def gridRows = getGridRows() return gridRows.size() } def shouldHaveARowWith(def map) { def gridRows = getGridRows() def matchingRowFound = true for(entry in map) { def gridRow = gridRows.find { row -> row[entry.key] == entry.value } matchingRowFound = gridRow != null } return matchingRowFound }
  • 52. Page Components @Test void theSummaryItemChangesToReflectTreeChoice() { page.itemTree.selectEntryCalled("Stuff to do") This is not an array assert page.itemSummaryGrid.size() == 1 def highlightedItemSummaryRow = page.itemSummaryGrid[0] assert highlightedItemSummaryRow.customerName == "ACME Inc" }
  • 53. ATDD, BDD and Page Objects Clean, precise, well-designed Powerful, robust, low-maintenance John  Ferguson  Smart Email:  [email protected] Web:  h"p://www.wakaleo.com Twi"er:  wakaleo