Selenium Page Objects and Abstraction

By on Jan 23, 2012 in eng |

Share On GoogleShare On FacebookShare On Twitter

Last Friday, I explained the concept of Selenium Page Objects to my colleague and I feel like I didn’t explain it in a simple way enough. I have spent some time today to come up with explanation that relates the page object pattern to the concept of abstraction in programming

Object Abstraction

Let’s say we have a class that processes news messages

class NewsListener{
    public void onNewsMessage(String rawMsg){
        //Example of raw message; "ID1234:Alert-News content" 
        String newsId = rawMsg.substring(0 , rawMsg.indexOf("-"));
        if( newsId.substring( newsId.indexOf(":") + 1 ).equals("Alert") ){  
            notifyAlertListener(newsId, rawMsg);
            renderNewsContent(newsId, rawMsg);

It seems like the NewsListener class know the news raw message really well. But the class is unlikely to be the only one that needs to get news ID and message type out of the raw message; AlertListener and NewsContentPanel may also need to use those values too. Although, those two lines of raw message parsing seems to be easy enough to be copied to all other classes but any decent developers know that will definitely causes problems

We can improve the code by introduce an abstraction; NewsMessage, to encapsulate the internal message format in one place and expose just the information that need to be used by other classes

public void onNewsMessage(NewsMessage msg){
        if( msg.isAlert() ){  

Selenium Page Objets

Let’s look at a test case to verify that the target page will not show any project information when there is no project stored in database

public class ListProjectPageTest {
    private static WebDriver driver;
    public static void setUpBeforeClass() throws Exception {
        driver = new FirefoxDriver();
    public void listProjectsWhenNoProjectInDB(){
        driver.get(  URLConfig.get(“list-project-page”)  );
        WebElement table = findElementIgnoreException( By.cssSelector("#container > table") );
        int numberOfProjShowing = table.findElements( By.xpath("tbody/tr") ).size();
        assertEquals(0, numberOfProjShowing );

Just like the NewsListener example, the test just want to assert the number of projects that have been showed on the target page but it choose to use Selenium driver to get the information directly from HTML DOM node. This code for retrieving the number of rows must be copied into every test case that needs the same information and the changes in HTML structure will risk breaking all those test cases

Page Objects is a pattern to capture web UI components into object. We can create ProjectsPage to encapsulate all the logic to get project’s information in one place and let our test cases work with our web UI at the higher level of abstraction

public void listProjectsWhenNoProjectInDB(){
ListProjectsPage page = ListProjectsPage.navigateToPage(driver);
	assertEquals(0, page.getNumberOfProjectsShowing() );

Below is example of how the page objects could be implemented

public class ListProjectsPage{
	private final WebDriver driver;
	private final WebElement tableElem;
	private ListProjectsPage(WebDriver driver) {
		tableElem = findElementIgnoreException( By.cssSelector("#container > table") );

	public static ListProjectsPage navigateToPage(WebDriver driver){
		driver.get( getURL("list-projects-page") );
		return new ListProjectsPage(driver);
	public int getNumberOfProjectsShowing(){
		return  tableElem.findElements( By.xpath("tbody/tr") ).size();

The pattern will make test cases less brittle and easy to read. Test cases will come close to the promise of “executable requirement”