Introduction:

Selenium is an open-source Web UI automation testing suite/tool. It supports automation across different browsers, platforms, and programming languages which includes Java, Python, C#, .net, Ruby, PHP, and Perl, etc. for developing automated tests. Selenium can be easily deployed on Windows, Linux, Solaris, and Macintosh Operating Systems. It also provides support for mobile applications like iOS, windows mobile, and Android for different Operating Systems.

Selenium consists of drivers specific to each language. Additionally, the Selenium Web driver is mostly used with Java and C#. 

Test scripts can be coded in selenium in any of the supported programming languages and can be run directly in most modern web browsers which include Internet Explorer, Microsoft Edge, Mozilla Firefox, Google Chrome, Safari, etc.

Furthermore, C# is an object-oriented programming language derived from C++ and Java.
It supports the development of console, windows, and web-based applications using Visual Studio IDE on the .Net platform.

With Selenium C#, there is a wide variety of automation frameworks that can be used for automated browser testing. Each framework has its own advantages and disadvantages, they are chosen on the basis of their requirement, compatibility, and the kind of solution they’d prefer. These are the most popular Selenium C# frameworks used for test automation.

NUnit:

It is a unit testing tool ported initially from JUnit for .Net Framework and is an Open Source Project. NUnit was released in the early 2000s, though the initial Nunit was ported from Junit, the recent .Net version 3 is completely rewritten from scratch.

To run the Nunit test we need to add attributes to our methods. An example, attribute [Test], Indicates the Test method. Below are the NuGet Packages required by NUnit

NUnit
NUnit3TestAdapter
Microsoft.NET.Test.Sdk 

XUnit:

XUnit is a unit testing tool for .Net Framework which was released in 2007 as an alternative to Nunit. xUnit has attributes for the execution of tests but is not similar to NUnit. [Fact] and [Theory] attributes are similar to [Test] 

Below are the NuGet Packages required by xUnit

Xunit
Xunit. runner.VisualStudio
Microsoft.NET.Test.Sdk

MSTest:

MSTest is a unit testing framework developed by Microsoft and ships with Visual Studio. However, Microsoft made version 2 open-source which can easily be downloaded. Additionally, MSTest has an attributes range similar to NUnit and provides a wide range of attributes along with parallel run support at the Class and Method level.

Prerequisite:

To get started with Selenium C# and the Page Object Model framework, first, we need to have the following things installed.

1) IDE: Download and install any IDE of your choice.

  •  Here we are using Microsoft Visual Studio 2022
  •  After downloading the Visual Studio Installer, select the .NET desktop development option and then click on Install.
  •  Now let the Visual Studio Installer download the packages and perform the installation.
  •  Install the latest version of the .NET Framework on your machine.

2) Create New Project: After the installation is over, begin using Visual Studio.

  •  select the Create a new project option, then select the xUnit Test Project option for C#.

3) Selenium Webdriver for Chrome Browser: You must also install Selenium’s web driver for Chrome browser.

  •  In Visual Studio navigate to Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution.
  • In the Search Bar, enter the name of the packages you want to install (e.g. Selenium .WebDriver).
  • Check the Project checkbox, and click on Install.
  • In the dialogue box asking to accept the licences click on Accept button.
  • This will start the installation process and install the Selenium WebDriver.

Selenium.WebDriver

This package contains the .NET bindings for concise and object-based

Selenium WebDriver API, which uses native OS-level events to manipulate the browser,
Selenium.Chrome.WebDriver (chrome driver exe)
This NuGet package installs Chrome Driver (Win32) for Selenium WebDriver in your xUnit Test Project.


Once Visual Studio is finished with the successful installation of the Selenium WebDriver, it will show a message in the output window.
Once the Visual Studio is set up with all dependencies, it’s ready for work.

Note: We will be using the demo testing website (https://www.calculator.net/) and trying to achieve the addition and subtraction operations for our automation test.

Writing the First Selenium C# Test:

Download the WebDriverManager from Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution.

WebDriverManager is an open-source Java Library that automates the management of driver executables required by Selenium WebDriverby performing the four steps (find, download, setup, and maintenance) for the drivers required for Selenium tests. Here are some benefits of WebDriverManager in Selenium:

  • WebDriverManager automates the management of WebDriver binaries, thereby avoiding installing any device binaries manually.
  • WebDriverManager checks the version of the browser installed on your machine and downloads the proper driver binaries into the local cache (~/.cache/selenium by default) if not already present.
  • WebDriverManager matches the version of the drivers. If unknown, it uses the latest version of the driver.
  • WebDriverManager offers cross-browser testing without the hassle of installing and maintaining different browser driver binaries.

In the UnitTest1 file, the final code looks like this:

public class UnitTest1
    {
        IWebDriver driver;
        CalculatorPage calc_page;
        public void Initialize_driver()
        {
         new WebDriverManager.DriverManager().SetUpDriver(new ChromeConfig());
            driver = new ChromeDriver();
          calc_page = new CalculatorPage();
        }
        public void Close_driver()
        {
        driver.Close();
        }
       [Fact]
        public void Add()
        {
            initialize_driver();
            calc_page.Initialize(driver);
            string actualresult = calc_page.calculate("14", "+", "5");
            Assert.Equal("19", actualresult);
            Close_driver();
        }
        [Fact]
        public void Subtract()
        {
            initialize_driver();
            calc_page.Initialize(driver);
            string actualresult = calc_page.calculate("24", "-", "5");
            Assert.Equal("19", actualresult);
           Close_driver()
        }
    }

Now just build your code by right-clicking the project xUnitTestProject1 or by pressing Ctrl + Shift + B and you will be able to see your test in “Test Explorer”.

After following the above procedure, run the test case. But this code will not execute unless the Chrome driver for the Selenium is not downloaded and unzipped on the system.

When developing a scalable and robust automation framework, it is important to consider the following challenges:

  1. Keeping up with UI changes: The primary goal of automated UI web tests is to validate the functionality of web page elements. However, the UI is subject to constant evolution, leading to changes in web locators. These frequent changes in web locators pose a challenge to code maintenance.
  2. Code maintenance: With the ever-changing UI, it is crucial to maintain the automation codebase effectively. Failing to update Selenium test automation scripts to reflect changes in web locators can result in test failures. Proper maintenance is essential to ensure the longevity and reliability of the test scripts.
  3. Test failure due to lack of maintenance: Inadequate maintenance of automation scripts can lead to scenarios where tests fail. One common cause is a change in web locators. If the Selenium test automation scripts are not updated accordingly, it can cause a significant number of tests to fail, impacting the overall test suite’s reliability.

So to address this, restructure the Selenium test automation scripts for increased modularity and reduced code duplication.

Utilizing the Page Object Model (POM) design pattern achieves code restructuring and minimizes the effort required for test code maintenance.

Now, let’s delve into a comprehensive overview of the Page Object Model, including the implementation and effective maintenance of your Selenium test automation scripts.

Why do we need Page Object Model in Selenium C#?

Selenium test automation scripts become more complex as the web applications add more features and web pages. With every new page added, new test scenarios are included in the Selenium test automation scripts. With this increase in lines of code, its maintenance can become very tedious and time-consuming. Also, the Repetitive use of web locators and their respective test methods can make the test code difficult to read.

Instead of spending time updating the same set of locators in multiple Selenium test automation scripts, a design pattern such as the Page Object Model can be used to develop and maintain code.    

What is Page Object Model In Selenium C#?

Page Object Model is the most widely used design pattern by the Selenium community for automation tests in which each web page (or significant ones) is considered as a separate class and a central object repository is created for controls on a web page.

  • Each Page Object (or page classes) contain the elements of the corresponding web page along with the necessary methods to access the elements on the page.
  • Thus it is a layer between the test scripts and UI and encapsulates the features of the page.
  • The Selenium test automation scripts do not interact directly with web elements on the page, instead, a new layer (i.e. page class/page object) resides between the test code and UI on the web page.  
  • Hence, Selenium test automation implementation that uses the Page Object Model in Selenium C# will constitute different classes for each web page thereby making code maintenance easier.
  • In complex test automation scenarios, automation scripts based on Page Object Model can have several page classes (or page objects). It is recommended that you follow a common nomenclature while coming up with file names (representing page objects) as well as the methods used in the corresponding classes. For example, if automation for a login page & dashboard page is to be performed, our implementation will have a class each for login & dashboard. The controls for the login page are in the ‘login page’ class and the controls for the dashboard page are in the ‘dashboard page’ class.


How to Use Page Object Model:

We will now implement the Page Object Model for the use case we considered above i.e. trying to achieve the addition and subtraction operations for our automation test on the Calculator page.
Create a class file – CalculatorPage.cs for Calculator page operation. This page class contains the locator information of the elements on that page. Also, we need to define the methods for that page in the CalculatorPage.cs class and call the methods from UnitTest1.cs.


We are initializing the Chromedriver object and launching the web page from the initialiseDriver() method from UnitTest1.cs. Also, we are creating the instance of CalculatePage from the same method.
The CalculatePage.cs contain an instance of IWebDriver and the following methods –

Initialize(): this method takes one IWebDriver object as an input parameter and it is assigned to a locally defined IWebDriver object. Also, the required web page is launched using this driver.

Calculate(): this method is actually used to do the calculation operation of two numbers..either addition or subtraction using 3 input parameters as user input number value1, number value 2, and operator like -’+’ or ‘-’. The required elements from the page are located and as per the operator, the required operation is performed on those.
The final code of CalculatePage.cs would look like the below:

public class CalculatePage
    {
        IWebDriver driver;

        public void Initialize(IWebDriver driver)
        {
            this.driver = driver;          
            driver.Navigate().GoToUrl("https://www.calculator.net/");
        }
       
    public string Calculate(string no1, string op, string no2)
        {
            IWebElement number1;
            char[] ch = no1.ToCharArray();

            for (int i = 0; i < no1.Length; i++)
            {
                number1 = driver.FindElement(By.XPath("//span[@onclick='r(" + ch[i] + ")']"));
                number1.Click();
             }

            IWebElement op_element = driver.FindElement(By.XPath("//span[@onclick=\"r('" +op + "')\"]"));
            op_element.Click();
            ch = no2.ToCharArray();

            for (int i = 0; i < no2.Length; i++)
            {
                number1 = driver.FindElement(By.XPath("//span[@onclick='r(" + ch[i] + ")']"));
                number1.Click();
            }
            IWebElement result = driver.FindElement(By.Id("sciOutPut"));
            string actual_result = result.Text.Trim();
            return actual_result;
      }
   }

Advantages of Page Object Model in Selenium C#:

Page Object Model is a widely used design pattern nowadays. It reduces code duplication, enhances code readability, and improves maintainability by emphasizing reusability and extensibility.
Furthermore, below are some of the major advantages of using the Page Object Model in Selenium C#.

Better Maintenance – With separate page objects (or page classes) for different web pages, functionality or web locator changes will have less impact on the change in test scripts. This makes the code cleaner and more maintainable as Selenium test automation implementation is spread across separate page classes.

Minimal Changes Due To UI Updates – The effect of changes in the web locators will only be limited to the page classes, created for automated browser testing of those web pages. This reduces the overall effort spent in changing test scripts due to frequent UI updates.

Reusability – The page object methods defined in different page classes can be reused across Selenium test automation scripts. This, in turn, results in a reduction of code size as there is increased usage of reusability with the Page Object Model in Selenium C#.

Simplification –One more important point of using this design pattern is that it simplifies the visualization of the functionality and model of the web page as both these entities are located in separate page classes. 

Execution:

Navigate to Test -> Run All Tests.
This will launch the test explorer in Visual Studio and will run our test. 

You can run the test from the command prompt or visual studio’s terminal (Developer Command Prompt) with the following command-

dotnet test

This dotnet test command is used to run the tests in the project in the current directory. The dotnet test command builds the solution and runs a test host application for each test project in the solution. While running the tests from the project, you can put different filters while running the test, like running the tests with particular tags, from specific projects, with particular names, etc.

You can find this framework in the following Git Repository.

spurqlabs/CSharp-Selenium-Page-Object-Model (github.com)

Conclusion:

Implementing the Page Object Model in Selenium with C# provides a structured approach to automation testing, making the code more maintainable and reusable. It simplifies the handling of UI changes and enhances the overall efficiency of the testing process for large-scale applications.

Read more blogs here

4