Implementing the Page Object Pattern in C# using Selenium WebDriver

Friday, 16 May 2014


What is Selenium WebDriver & What Does it do?

Selenium WebDriver is a library that can be used to create automated tests for a web application. Selenium WebDriver provides an API that gives you access to a load of functions that interact with a browser through your code.


What is The Page Object Pattern?

The Page Object Pattern is a design pattern that is used in test automation that increases the maintainability of the code, and reduces code duplication. The Page Object pattern provides a separation between the code needed to build a page, and the code being written to test that page.

The Page Object Pattern basically says that each page in an application should have a class with methods to represent all the things that can be done on a page. So a page object for a login page may have a login method, that takes in a username and password, to simulate a user logging into an application.


Implementing the Page Object Pattern

The code samples below show how I've implemented the Page Object Pattern to test a login page for an application.

One of the first classes I created was the Browser class. The Browser class is a static class that contains functions that allow us to interact with the internet browser we are running our tests in. I will go through the code in the browser class in another post, but will explain any methods called from it. If you're interested in seeing the code you can have a look at it here.

This next class I created was the PageObject Class. As you begin to develop more page objects, you may find some common functionality between them. I have grouped these bits of functionality into a base class that all pages I create will inherit from. The PageObject class contains all the basic methods and properties a page will need, such as a pageTitle property and a GoTo method. I have also made this class an Abstract class, mainly because I do not want there to be instances of this class, as it is not complete.

The code for the PageObject class can be seen below:

 
			public abstract class PageObject
			{
				internal static string PageTitle { get; set; }
				internal static string Url { get; set; }
				
				protected PageObject()
				{
					Url = EnvironmentReader.get(GetType().Name).Url;
					PageTitle = EnvironmentReader.get(GetType().Name).PageTitle;
				}
				
				internal void WaitForLoad()
				{
				   var wait = Browser.Wait();

				   try
				   {
					   wait.Until(p => p.Title == PageTitle);
				   }
				   catch (Exception e)
				   {
					   Console.WriteLine(e.Message);
					   TakeScreenshot();
					   throw;
				   }
					
				}
 
				public bool IsAt()
				{
					return Browser.Title.Contains(PageTitle);
				}
			
				public void Goto()
				{
					try
					{
						Browser.Goto(Url);
						WaitForLoad();
					}
					catch (Exception e)
					{
						throw new Exception(GetType().Name + " could not be loaded. Check page url is correct in app.config." +
											" " + e.Message);
					}
				}
			}
		

The PageObject class has two properties, pageTitle & Url. The pageTitle property is set when the page is created and should store the title the page should have, when it is loaded in the browser.
This gives us the ability to determine if we are at a page by checking if the title displayed in the browser matches the page we expect the application to be at.
This is illustrated by the method IsAt. This method uses the Title property of the browser object, which stores the current title of the page the browser is displaying, and checks if it contains the title of this page.

The Url property of the pageObject class stores the Url the user needs to enter into the browser to reach the page. By having this property, we can always navigate to the page, by calling the GoTo Method.
The GoTo method is a simple pass through method that calls the Goto Method of the Browser object, with the Url of this page as a parameter.

After creating the pageObject class, we can create the Login Page

		
			public class LoginPage : PageObject
			{

				[FindsBy(How = How.Id, Using = "username")]
				private IWebElement txtUserName;

				[FindsBy(How = How.Id, Using = "password")]
				private IWebElement txtPassword;

				[FindsBy(How = How.Id, Using = "logon")]
				private IWebElement btnLogOn; 
				 
				public bool LogOn(string userName, string password)
				{
					WaitForLoad();
					txtUserName.SendKeys(userName);
					txtPassword.SendKeys(password);

					btnLogOn.Click();
				}

			} 
		

The login page inherits from the page object class, so will have access to all the methods that have been defined there, including the IsAt function.

The login page has three properties, which give access to the Username & Password text box and the logon button.
The LogOn method takes in two parameters, the username and password needed to logon. When the method is executed, the WaitForLoad method is called to pause execution until the page is loaded. The values passed in for username and password are then sent to the corresponding textboxes before the logon button is clicked.

Now that the login page object is complete, I can write my test using the new class i have created.

			[TestClass]
			public class Test1
			{
				[TestInitialize]
				public void SetupTest()
				{
					Browser.Open();
				}

				[TestMethod]
				public void LoginTestDemo()
				{
					Pages.LoginPage.LogOn();

					Assert.IsFalse(Pages.LoginPage.IsAt());
				}

				[TestCleanup]
				public void TestCleanup()
				{
					Browser.Quit();
				}
			}