A couple of words about Page Object

Often in the testing of web applications, every form on a page is described as a separate entity (object) – usually, one single form (in most cases it represents an isolated functionality) is equal to a separate class. All these objects/classes consist of web element instances (various web elements located on the related web form) and methods for interaction with the elements. Let’s imagine there is a Login form in a web application. The form may be described as:

public class Login
{
   IWebDriver driver;
   public Login(IWebDriver driver) { this.driver = driver; }
   //the class contains only one method
   //this is abridged example of the method. There is neither verification for null reference exception, nor check of driver’s actions, nor logging of events, nor handling of exceptions.
   //The method takes two strings as parameters: user name and password, and returns an instance of the web application start page - StartPage
   public StartPage LogIn(string userName, string pwd)
   {
      IWebElement name = driver.FindElement(By.nameTextboxLocator);
      name.SendKeys(userName);
      IWebElement pwd = driver.FindElement(By.passwordTextboxLocator);
      pwd.SendKeys(userPassword);
      IWebElement btnLogin = driver.FindElement(By.loginButtonLocator);
      btnLogin.Click();
      return new StartPage([parameters]);
   }
}

Therefore, the test would be looking like this:

[Test]
public class LogIn()
{
   driver.Navigate().GoTo(http://address-of-tested-login-page.com);
   var Page_Login = new Login(driver);
   var StartPage = Page_Login.LogIn(userName, password);
   Assert.IsTrue(StartPage.VerifyStartPageIsLoaded());
}

This approach allows you to create a big number of tests very fast and easy. But there are a number of underwater stones hidden inside as well. This way of writing new tests is good enough for little and simple projects where there are only a couple of hundreds of web elements and methods. and were only a few persons are doing the testing. Because, if the tested web application is very complex or the application is developed very fast and a lot of functionalities are often changed or you have a big team of automated testers (and most of them are juniors), it is likely that the maintenance of the framework will be your nightmare. Because sometimes you will be forced and called upon to maintain the framework.

A simple example: what if after clicking LogIn button a dozen of other different pages may be loaded in addition to StartPage? For example, imagine that according to the type of user’s contract, his role, profile settings, user location (the country where the request has come from) and settings of the testing environment (server which the user is connected through), there may be loaded eighteen different pages. In this case, you should override the method eighteen times to get all the pages, and after some time you should maintain all these versions of the method if something has been changed in the application. Of course, you can use a generic method aka <T>Login(username, password) in your tests but we’re talking about a maximum ease of writing and understanding of tests. It’s hard to imagine that a customer or PM or manual tester at least superficially understand the generics.

The second underwater stone is the scaling. If you described a page or some of its part as a single object and one day something is changed of this page (or its part) you will have to update the object itself, its methods (there may be a lot of ones) and related tests (the number of such tests may be actually huge). In general, the causes from above are already sufficient to decide not to implement the Page Object pattern to web pages or forms but to implement the pattern to page’s elements. In my approach, an object I will interact with is a web element, not the entire page. You may call it Element Object. I describe every single web page (or web form) as a separate class and it still contains a set of web elements located on the related web page but there are no methods for interaction with its elements. Instead, the web elements (buttons, links, images, tables, etc.) are described as the page’s properties. Every element is defined in its own class and has its own methods for interaction. Thus, the Page Object pattern is implemented in relation to web elements, not web pages.

Please, keep in mind that the bigger and complex object is the more difficult is its maintenance. You can describe, for example, the entire login form as a single entity or you can describe separately every element of this form as a single entity. The second approach will be more flexible.

Example:

public class Login
{
   //the class contains a set of properties, not methods
   //this is full description of login form. No additional verification, actions or logging is required.Everything, together with all properties and methods of every element, is encapsulated inside appropriate web element class
   public Textbox Textbox_UserName { get { return new Textbox(“locator of the element on the page”, [other parameters]); } }
   public Textbox Textbox_Password { get { return new Textbox(“locator of the element on the page”, [other parameters]); } }
   public Textbox Button_LogIn { get { return new Button(“locator of the element on the page”, [other parameters]); } }
}
[Test]
public void TestLogIn()
{
   TestedApplication.Page_Login.Textbox_UserName.TypeText(userName);
   TestedApplication.Page_Login.Textbox_Password.TypeText(password);
   TestedApplication.Page_Login.Button_Login.Click();
   Assert.IsTrue(TestedApplication.Page_StartPage.IsLoaded);
}

Author: Oleh Husiev, Anastasia Husieva

Test Automation engineer at Namecheap, Kharkiv, Ukraine. Student of Kharkiv Politechnical University, Kharkiv, Ukraine.

Leave a Reply

Your email address will not be published. Required fields are marked *