Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
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
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();
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?
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
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
}
}
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
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){...}
...
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