Page Object Model tutorial using selenium webdriver in C#, Visual Studio and VS UnitTest (for dummies!)

In this tutorial I’ll give you a dummies guide to the Page Object Model design pattern with a simple example in C#.

This tutorial will assume you already understand basic selenium webdriver implemented in C#. If not you need to go look-up some entry-level tutorials before you’ll be able to make use of this tutorial. You will also need to understand what a design pattern is and have a good grasp of object-oriented programming in C#.

Introduction to Page Object Model

In the page object model design pattern, we represent a webpage as an object and its UI functions (that being anything on the page we could interact with) as a method of the object.

Why?

Firstly, it lets up separate the test specification from the test implementation. A test specification tells us what to test, the test implementation is how we test, which we can now hide under the code of the class representing the page and its functions. This abstraction keeps things clear and makes the specification of the test nice and clear.

Secondly, its extremely robust. If there are any changes in the application under test – for example a new element is added to the user interface, or the identifier used by webdriver to find an element changes, the code needs to be changed in only one place (look up the singleton design pattern for a more thorough look at this approach to object oriented programming). As a rule of thumb we hide all the html under the page object and never look at it in the specification, keeping our code neat and easily manageable.

Thirdly, its laconic and easy to write. Once the objects and methods for the page are created, very succinct tests can be written that are easy to read. Compare this example of opening a Google page and searching for a search term:

driver.Navigate().GoToUrl(homepage);
driver.FindElementById("gbqfq").SendKeys(searchTerm);
driver.FindElementById("gbqfb").Click();

With this example:

GooglePage pageObject = new GooglePage();

pageObject.openPage(homepage, driver);
pageObject.searchFor(searchTerm, driver);
pageObject.clickSearch(driver);

Basic tutorial

Here is the most bare-bones example I could imagine for this exercise – a Google search. In this example we take the Google homepage and create a class to represent it (GooglePage) in the GoogleHomePageObject.cs file, included in the POMtest namespace, then call it and its functions – the UI elements on the page – from a main class POMtest. As noted earlier, this tutorial assumes you know the basics of selenium in C# but to recap: make sure you have your references set up to selenium (easily done through the NuGet Package Manager or by right-clicking References in the Solution Explorer window and adding the selenium references if you have the dll’s on your local machine) and that you have Visual Studio Unit Testing Framework set up (again, easily done by adding the correct reference). This test could just as easily be run through Nunit if preferred, just adjust import and reference the appropriate library.

To save time I created the base for these tests in Visual Studio 2010 by clicking Test–> New Test and following the wizard to create a new test solution and test class. As this tutorial assumes some knowledge of C# and Visual Studio you may have another way of reaching this same point.

Here’s the code for the main class, from which we will call the code:

//POMtest.cs
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
//using OpenQA.Selenium.Chrome;

namespace POMtest
{
[TestClass]
public class POMtest
{

[TestMethod]
public void RunTests()

{

FirefoxDriver driver = new FirefoxDriver();

//ChromeDriver driver = new ChromeDriver();
string homepage = "http://google.co.uk";

// driver.Navigate().GoToUrl(baseURL);
string searchTerm = "Manual testing is long";

GooglePage pageObject = new GooglePage();

pageObject.openPage(homepage, driver);
pageObject.searchFor(searchTerm, driver);
//pageObject.clickSearch(driver);

/*driver.FindElement(By.LinkText("Projects")).Click();
driver.FindElement(By.LinkText("Selenium IDE")).Click();
Assert.AreEqual(driver.FindElement(By.XPath("//div[@id='mainContent']/table/tbody/tr/td/p/b")).Text, "Selenium IDE");
*/

driver.Close();

}
}

}

And here’s the heart of the matter – an actual page object:

//GoogleHomePageObject.cs
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;
//using OpenQA.Selenium.Chrome;

namespace POMtest
{

public class GooglePage
{

public void openPage (string homepage, FirefoxDriver driver)
{

//driver.Navigate().GoToUrl("http://google.co.uk");
driver.Navigate().GoToUrl(homepage);
//Console.WriteLine(homepage);
// driver.Navigate();
}

public void searchFor(string searchTerm, FirefoxDriver driver)
{
//Selenese goes here
//driver.FindElementsByClassName("gbqfif").Click();
driver.FindElementById("gbqfq").SendKeys(searchTerm);
}

public void clickSearch(FirefoxDriver driver)
{
//Selenese goes here
driver.FindElementById("gbqfba").Click();
}

public void clickFeelingLucky(FirefoxDriver driver)
{
//Selenese
driver.FindElementById("gbqfbb").Click();
}

}
}

Compile in two separate files and viola!

Some further considerations

To keep this to a ‘for dummies’ guide, I have only made a point of introducing only the basic concept above, but there is more to this design pattern. Test validation (assert and verify statements) deserve special mention. These should wherever possible be handled by the test specification, which is to say the calling class, not the test implementation, which is to say the page objects. If the page object represents the application under test and the calling class the test itself, it stands to reason the test itself should be validating the test output.

Secondly, each method should have only one possible outcome. Each separate outcome of an interaction with a UI element on a website should have a separate method within the class – so for a website with a login function, we might want two methods for Login and Login_Unsuccessful.

Finally, you wouldn’t want to run your entire test suite this way without first building some kind of framework. Look at the framework in the references below to see one excellent example of a C# POM selenium framework.

References

The Google Code tutorial, the best resource I’ve personally found

An excellent example framework by a Mr Alistair Scott

A more detailed blog post on POM with more theory than in the Google Code explanation

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s