Before jumping into the details of this chapter of Encapsulate Selenium Page Objects, let's just understand what is the most important Object Oriented Programming Principle. It very is necessary for us to implement the same principle in the Test Framework as well. It helps to make the code more secure, readable and maintainable.

Encapsulation - OOPs Principle

Encapsulation in Java is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. In encapsulation the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class, therefore it is also known as data hiding.

To achieve encapsulation in Java

  • Declare the variables of a class as private.
  • Provide public setter and getter methods to modify and view the variables values.

Accessor - Get()

An accessor is a method that is used to ask an object about itself. In OOP, these are usually in the form of properties, which have, under normal conditions, a get method, which is an accessor method. However, accessor methods are not restricted to properties and can be any public method that gives information about the state of the object.

Mutator - Set()

Mutators are public methods that are used to modify the state of an object, while hiding the implementation of exactly how the data gets modified. Mutators are commonly another portion of the property discussed above, except this time it's the set method that lets the caller modify the member data behind the scenes.

  public class EncapTest
	{
		private int Age;
		public int GetAge()
		{
			return Age;
		}
		public void SetAge(int age)
		{
			Age = age;
		}

	}

Advantages

  • The fields of a class can be made read-only or write-only.
  • A class can have total control over what is stored in it's fields.
  • The users of a class do not know how the class stores its data. A class can change the data type of a field and users of the class do not need to change any of their code.

Encapsulate Selenium Page Objects

With the above assumption in our Framework, we should make all the Page Objects as Private.

[FindsBy(How = How.Id, Using = "account")][CacheLookup] private IWebElement MyAccount{ get; set; }

But the problem is, once the MyAccount property is changed to private, you will notice the script error in the test.

Encapsulate Selenium Page Objects

As the property is no more public, it is no more accessible in any other class but itself. To overcome this, it is required to write an Accessor for the element. Which will be like this.

public void ClickOnMyAccount() {        MyAccount.Click(); }

Once you implement the above code, the test script will be changed to this:

var homePage = new HomePage(driver); homePage.ClickOnMyAccount();

Implementation of Encapsulation in Automation Framework

LogInTest.cs TestCase

using NUnit.Framework;
using OnlineStore.PageObjects;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;

namespace OnlineStore.TestCases
{
    class LogInTest
    {
        [Test]
        public void Test() {

            IWebDriver driver = new FirefoxDriver();
            driver.Url = "https://www.store.demoqa.com";

            var homePage = new HomePage(driver);
            homePage.ClickOnMyAccount();

            var loginPage = new LoginPage(driver);
            loginPage.LoginToApplication();

            driver.Close();
        }    
    }
}

HomePage PageObject Class

using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;

namespace OnlineStore.PageObjects
{
    class HomePage
    {
        private IWebDriver driver;

        [FindsBy(How = How.Id, Using = "account")]
        [CacheLookup]
        private IWebElement MyAccount { get; set; }

        public HomePage(IWebDriver driver)
        {
            this.driver = driver;
            PageFactory.InitElements(driver, this);
        }

        public void ClickOnMyAccount()
        {
            MyAccount.Click();
        }
    }
}

LogInPage PageObject Class

using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;

namespace OnlineStore.PageObjects
{
    class LoginPage
    {
        private IWebDriver driver;

        [FindsBy(How = How.Id, Using = "log")]
        [CacheLookup]
        private IWebElement UserName { get; set; }

        [FindsBy(How = How.Id, Using = "pwd")]
        [CacheLookup]
        private IWebElement Password { get; set; }

        [FindsBy(How = How.Id, Using = "login")]
        [CacheLookup]
        private IWebElement Submit { get; set; }

        public LoginPage(IWebDriver driver)
        {
            this.driver = driver;
            PageFactory.InitElements(driver, this);
        }

        public void LoginToApplication()
        {
            UserName.SendKeys("TestUser_1");
            Password.SendKeys("Test@123");
            Submit.Submit();
        }
    }
}

Notice that in above LogInPage class, we have not created any Accessor or Mutator for Username & Password field. Although all the properties have been changed to private now. The reason is, so far in the LogInTest, we have not used Username & Password directly. The test call the LoginToApplication() method to do the thing. So the point is it is not useful to create object methods till the time test makes use of it. Otherwise the PageObject class will end up with hundreds of object methods.

Optimizing Page Object Model
Optimizing Page Object Model
Previous Article
Manage And Read Configurations using ConfigurationManager in C#
Manage And Read Configurations using ConfigurationManager in C#
Next Article
Lakshay Sharma
I’M LAKSHAY SHARMA AND I’M A FULL-STACK TEST AUTOMATION ENGINEER. Have passed 16 years playing with automation in mammoth projects like O2 (UK), Sprint (US), TD Bank (CA), Canadian Tire (CA), NHS (UK) & ASOS(UK). Currently, I am working with RABO Bank as a Chapter Lead QA. I am passionate about designing Automation Frameworks that follow OOPS concepts and Design patterns.
Reviewers
Virender Singh's Photo
Virender Singh

Similar Articles

Feedback