When learning test automation with Selenium, the Page Object Model is useful for creating classes that correspond to site pages (or components of pages) so that the WebDriver APIs are moved from the test scripts to the page object classes.
After you create page object classes, make sure that each page object method returns either
- A PAGE OBJECT: if the method generates a page change or a new page (example: changing the sort order for a web page will reload the page)
or
- THIS KEYWORD: if the method's action does not change anything in the page (example: typing a keyword into a textbox does not change anything else in the page)
To see the benefits of returning objects from page object methods, lets look at a simple test case with the following steps:
1. open the home page of a web site
2. do a keyword search
3. after the results page is loaded, change the sort order
4. after the results page reloads as a result of changing the sort order, select a different results page (page number 5)
5. after the 5th results page is loaded, change the number of results displayed in the page
6. after the page reloads, select one of the results
7. after the result's details page is loaded, confirm that the result's price is valid
The test script for the test case needs 3 page object classes:
public class HomePage
{
public void search()
}
public class ResultsPage
{
public void changeSortOrder(String sortOrder)
public void changeResultsPerPage(int number)
public void changePage(int pageNumber)
public void selectResult(int index)
}
public class DetailsPage
{
public Boolean validPrice()
}
None of the page object methods returns an object.
The test script looks as follows:
@Test
public void testValidPrice()
{
HomePage homePage = new HomePage();
homePage.search();
ResultsPage resultsPage = new ResultsPage();
resultsPage.changeSortOrder("author");
resultsPage.changePage(5);
resultsPage.changeResultsPerPage(25);
resultsPage.selectResult(3);
DetailsPage detailsPage = new DetailsPage();
assertTrue(detailsPage.validPrice(), true);
}
The problems of the test script are evident:
- too many new objects are being created (homePage, resultsPage, detailsPage)
- each action is separate
- the flow of the test script does not follow user actions: when the user changes the sort order on the ResultsPage, a new ResultsPage is created as a result
Lets change the page object classes so that all page object methods return objects:
public class HomePage
{
public ResultsPage search();
}
public class ResultsPage
{
public ResultsPage changeSortOrder(String sortOrder)
public ResultsPage changeResultsPerPage(int number)
public ResultsPage changePage(int pageNumber)
public DetailsPage selectResult(int index)
}
public class DetailsPage
{
public Boolean validPrice()
}
@Test
public void testValidPrice()
{
DetailsPage detailsPage = (new HomePage()).search().changeSortOrder("author").changePage(5).changeResultsPerPage(25).selectResult(3);
assertTrue(detailsPage.validPrice(), true);
}
Multiple improvements result from the new page object classes:
- multiple methods can be chained
- the test script is much more compact
- less objects are created