Page Objects with Partial Classes and Properties- WebDriver C#

Page Objects with Partial Classes and Properties- WebDriver C#

Editorial Note: I originally wrote this post for the Test Huddle Blog. You can the original text on their site.

This is the second article from the WebDriver Page Objects Series. It is dedicated to creating page objects with partial classes without the Selenium.Support NuGet.

In my previous article from the series, I showed you how to use the standard page object model that comes from the Selenium.Support NuGet. However, I believe it has a couple of drawbacks. First, you need to install an additional NuGet package, which is an extra code dependency. Moreover, you do not have a full control over how the elements are located though the PageFactory class and the FindsBy attributes. If you want to create a SelectElement, you cannot since the FindsBy variables/properties return directly IWebElement.

Two years ago while we were working on the first version of the BELLATRIX test automation framework, I did this research so that we can find the most convenient way for creating page objects.

Test Case

For the examples, I will use once again the SearchEngine’s home page, called SearchEngineMainPage. The main test case on this page is to search for a term and then assert the count of the returned results.

SearchEngine main page

Page Objects through Partial Classes Revised

SearchEngineMainPage class’s definition:

  • SearchEngineMainPage

    Contains the constructor(s) and the action methods

  • SearchEngineMainPage.Map

    Stores all web elements’ properties

  • SearchEngineMainPage.Asserter

    holds all assertions

  • Product installer services

SearchEngineMainPage

using OpenQA.Selenium;
namespace HuddlePageObjectsElementsStringProperties.ImprovedVersion
{
    public partial class SearchEngineMainPage
    {
        private readonly IWebDriver _driver;
        private readonly string url = @"searchEngineUrl";
        public SearchEngineMainPage(IWebDriver browser)
        {
            _driver = browser;
        }
        public void Navigate()
        {
            _driver.Navigate().GoToUrl(url);
        }
        public void Search(string textToType)
        {
            SearchBox.Clear();
            SearchBox.SendKeys(textToType);
            GoButton.Click();
        }
    }
}

The only difference with the previous version of this file is that we do not call PageFactory.InitElements(browser, this); in the constructor.

SearchEngineMainPage.Map

using OpenQA.Selenium;
namespace HuddlePageObjectsElementsStringProperties.ImprovedVersion
{
    public partial class SearchEngineMainPage
    {
        public IWebElement SearchBox
        {
            get
            {
                return _driver.FindElement(By.Id("sb_form_q"));
            }
        }
        public IWebElement GoButton
        {
            get
            {
                return _driver.FindElement(By.Id("sb_form_go"));
            }
        }
        public IWebElement ResultsCountDiv
        {
            get
            {
                return _driver.FindElement(By.Id("b_tween"));
            }
        }
    }
}

The primary discrepancy between the two versions is here. We locate the elements though the WebDriver’s FindElement method instead of using the FindsBy attributes.

If you are using WebDriver often, you may find useful my Most Complete Selenium WebDriver C# Cheat Sheet. All you need to know- the most basic operations to the most advanced configurations.

SearchEngineMainPage.Asserter

using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace HuddlePageObjectsElementsStringProperties.ImprovedVersion
{
    public partial class SearchEngineMainPage
    {
        public void AssertResultsCount(string expectedCount)
        {
            Assert.AreEqual(ResultsCountDiv.Text, expectedCount);
        }
    }
}

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

In future articles, I will share with you other modifications of the design pattern that can make your tests even more maintainable.

For more detailed overview and usage of many more design patterns and best practices in automated testing, check my book “Design Patterns for High-Quality Automated Tests, C# Edition, High-Quality Tests Attributes, and Best Practices”.  You can read part of three of the chapters:

Defining High-Quality Test Attributes for Automated Tests

Benchmarking for Assessing Automated Test Components Performance

Generic Repository Design Pattern- Test Data Preparation

Related Articles

Design Patterns

Strategy Design Pattern in Automated Testing

In my previous articles from the series "Design Patterns in Automated Testing", I explained in details how to make your test automation framework better through

Strategy Design Pattern in Automated Testing

Design Patterns

Observer Design Pattern Classic Implementation in Automated Testing

The Observer Design Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updat

Observer Design Pattern Classic Implementation in Automated Testing

Design Patterns

Generic Repository Design Pattern- Test Data Preparation

Often we can run the tests against an empty DB. However, we still need initial data. We can generate it ourselves. To do so, we need to add a code for accessing

Generic Repository Design Pattern- Test Data Preparation

Design Patterns

Advanced Specification Design Pattern in Automated Testing

In my last publication from the Design Patterns in Automated Testing Series, I explained to you how you can benefit from the usage of the Specification Design P

Advanced Specification Design Pattern in Automated Testing

Design Patterns

Rules Design Pattern in Automated Testing

Separate the logic of each individual rule and its effects into its own class. Separate the selection and processing of rules into a separate Evaluator class.

Rules Design Pattern in Automated Testing

Design Patterns

Page Objects That Make Code More Maintainable

If you have read some of my previous posts, most probably you have checked some of my articles about Design Patterns in Automated Testing. One of the most promi

Page Objects That Make Code More Maintainable
Anton Angelov

About the author

Anton Angelov is Managing Director, Co-Founder, and Chief Test Automation Architect at Automate The Planet — a boutique consulting firm specializing in AI-augmented test automation strategy, implementation, and enablement. He is the creator of BELLATRIX, a cross-platform framework for web, mobile, desktop, and API testing, and the author of 8 bestselling books on test automation. A speaker at 60+ international conferences and researcher in AI-driven testing and LLM-based automation, he has been recognized as QA of the Decade and Webit Changemaker 2025.