Click here to Skip to main content
13,899,733 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

4.5K views
1 bookmarked
Posted 16 Apr 2017
Licenced Ms-PL

Enhanced Selenium WebDriver Page Objects through Partial Classes

, 16 Apr 2017
Rate this:
Please Sign up or sign in to vote.
Find how to create more refined and more maintainable page objects in WebDriver. These page objects will follow more closely the Single Responsibility Principle.

Introduction

One of the most popular design patterns in Web Automation is the so-called Page Object Pattern. The famous programmer Martin Fowler was one of the first that mentioned Page Object as a pattern and explained its usage. You may not be able to find it in the list of all "official" design patterns because the community started using it recently. Most of the other design patterns have been about for more than 20 years. You can find more about the usage of design patterns in the automated testing in my series- Design Patterns in Automated Testing Series.

In general, a page object abstracts an HTML page. It provides an easy to use interface for manipulating the page elements without searching for them in the HTML.

Selenium WebDriver Page Objects

using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.PageObjects;

namespace ImprovedPageObjects
{
    public class BingMainPage
    {
        private readonly IWebDriver driver;
        private readonly string url = @"http://www.bing.com/";

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

        [FindsBy(How = How.Id, Using = "sb_form_q")]
        public IWebElement SearchBox { get; set; }

        [FindsBy(How = How.Id, Using = "sb_form_go")]
        public IWebElement GoButton { get; set; }

        [FindsBy(How = How.Id, Using = "b_tween")]
        public IWebElement ResultsCountDiv { get; set; }

        public void Navigate()
        {
            this.driver.Navigate().GoToUrl(this.url);
        }

        public void Search(string textToType)
        {
            this.SearchBox.Clear();
            this.SearchBox.SendKeys(textToType);
            this.GoButton.Click();
        }

        public void AssertResultsCount(string expectedCount)
        {
            Assert.AreEqual(this.ResultsCountDiv.Text, expectedCount);
        }
    }
}

In the example, the different properties represent the various elements of the pages. They are located through the help of the FindsBy attributes that are holding the finding strategy. Below them, you can find the different actions that can be performed on the page.

To use the code from the example, you need to install two NuGet packages - Selenium.WebDriver (holding the main WebDriver interfaces) and Selenium.Support (provides the page objects' support). If you use Selenium WebDriver on a daily basis maybe, you will find the cheat sheet that I created to be useful.

The usage in tests is straightforward. You only create an instance of the page and call some of the action methods and at the end - one of the assertions.

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Firefox;

namespace ImprovedPageObjects
{
    [TestClass]
    public class BingTests
    {
        private IWebDriver driver;

        [TestInitialize]
        public void SetupTest()
        {
            this.driver = new FirefoxDriver();
            this.driver.Manage().Timeouts().ImplicitlyWait(new TimeSpan(0, 0, 30));
        }

        [TestCleanup]
        public void TeardownTest()
        {
            this.driver.Quit();
        }

        [TestMethod]
        public void SearchTextInBing_First()
        {
            var bingMainPage = new BingMainPage(this.driver);
            bingMainPage.Navigate();
            bingMainPage.Search("Automate The Planet");
            bingMainPage.AssertResultsCount("236,000 RESULTS");
        }
    }
}

What Is the Problem with this Approach?

If you automate a page with lots of elements and complex logic, the code of the class can get enormous. Larger files increase the search time and decrease the readability of the page object. This is so because the class contains three different types of elements. The web page properties, the action methods and the assert methods. Usually, when you need to fix something in the page object, you need to change only one of these items.

One way to handle this problem is to separate these three types in different files. However, I want the usage of the page object to stay the same. You can use one of the features of C# - the partial classes.

Enhanced Page Objects through Partial Classes

You can read more about the partial classes and methods in the official MSDN documentation. But in general, it is possible to split the definition of a class over two or more source files. Each source file contains a section of the type or method definition, and all parts are combined when the application is compiled. Using this approach, the BingMainPage classes' definition will be placed inside three different files:

  • BingMainPage - contains the constructor(s) and the action methods
  • BingMainPage.Map - stores all web elements' properties
  • BingMainPage.Asserter - holds all assertions

BingMainPage

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

namespace ImprovedPageObjects.ImprovedVersion
{
    public partial class BingMainPage
    {
        private readonly IWebDriver driver;
        private readonly string url = @"http://www.bing.com/";

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

        public void Navigate()
        {
            this.driver.Navigate().GoToUrl(this.url);
        }

        public void Search(string textToType)
        {
            this.SearchBox.Clear();
            this.SearchBox.SendKeys(textToType);
            this.GoButton.Click();
        }
    }
}

BingMainPage.Map

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

namespace ImprovedPageObjects.ImprovedVersion
{
    public partial class BingMainPage
    {
        [FindsBy(How = How.Id, Using = "sb_form_q")]
        public IWebElement SearchBox { get; set; }

        [FindsBy(How = How.Id, Using = "sb_form_go")]
        public IWebElement GoButton { get; set; }

        [FindsBy(How = How.Id, Using = "b_tween")]
        public IWebElement ResultsCountDiv { get; set; }
    }
}

BingMainPage.Asserts

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ImprovedPageObjects.ImprovedVersion
{
    public partial class BingMainPage
    {
        public void AssertResultsCount(string expectedCount)
        {
            Assert.AreEqual(this.ResultsCountDiv.Text, expectedCount);
        }
    }
}

The usage of the page object in tests stays the same.

So Far in the "Design Patterns in Automated Testing" Series

  1. Page Object Pattern
  2. Advanced Page Object Pattern
  3. Facade Design Pattern
  4. Singleton Design Pattern
  5. Fluent Page Object Pattern
  6. IoC Container and Page Objects
  7. Strategy Design Pattern
  8. Advanced Strategy Design Pattern

The post Enhanced Selenium WebDriver Page Objects through Partial Classes appeared first on Automate The Planet.

All images are purchased from DepositPhotos.com and cannot be downloaded and used for free.

License Agreement

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

Anton Angelov
CEO Automate The Planet
Bulgaria Bulgaria
Anton Angelov is an IT Consultant and Quality Assurance Architect at Innovative Lab. He is passionate about automation testing and designing test harness and tools, having the best industry development practices in mind. In addition, he is an active blogger and the founder of Automate The Planet. He strives to make the site one of the leading authorities in Automation Testing by presenting compelling articles, inspiring ardent discussions amongst the community. He is also one of the most-rated-answer authors of questions about Test Automation Frameworks (WebDriver) on Stack Overflow.

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01 | 2.8.190306.1 | Last Updated 16 Apr 2017
Article Copyright 2017 by Anton Angelov
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid