Search code examples
c#selenium-webdriverautomated-testsnunit

Implement Page-Object models in C# Selenium - PageFactory


I am very new to the test automation.

  1. I run Visual Studio 2022, Version 17.6.2
  2. I have NuGet packages: Selenium.WebDriver, Selenium.Support, Selenium.Chrome.WebDriver, Gherkin, NUnit, NUnit3TestAdapter, xunit, BoDi, SpecFlow.Internal.Json

I try to implement the POM model testing using an example I found on the web.

POM:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenQA.Selenium.Support.PageObjects;
using OpenQA.Selenium;

namespace POMExample.PageObjects
{
    internal class HomePage
    {
        private IWebDriver driver;

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

        [FindsBy(How = How.CssSelector, Using = ".fusion-main-menu a[href*='about']")]
        private IWebElement about;

        [FindsBy(How = How.ClassName, Using = "fusion-main-menu-icon")]
        private IWebElement searchIcon;

        public void goToPage()
        {
            driver.Navigate().GoToUrl("http://www.swtestacademy.com");
        }

        public AboutPage goToAboutPage()
        {
            about.Click();
            return new AboutPage(driver);
        }
    }
}

Test

using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using POMExample.PageObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace POMExample
{
    public class TestClass
    {
        private IWebDriver driver;

        [SetUp]
        public void SetUp()
        {
            driver = new ChromeDriver();
            driver.Manage().Window.Maximize();
        }

        [Test]
        public void SearchTextFromAboutPage()
        {
            HomePage home = new HomePage(driver);
            home.goToPage();
            AboutPage about = home.goToAboutPage();
            ResultPage result = about.search("selenium c#");
            result.clickOnFirstArticle();
        }

        [TearDown]
        public void TearDown()
        {
            driver.Close();
        }
    }
}

However POM Indicates errors:

The type or namespace name 'PageObjects' does not exist in the namespace 'OpenQA.Selenium.Support'

The name 'PageFactory' does not exist in the current context

etc...

see the screenshot below:

enter image description here

using OpenQA.Selenium.Support.PageObjects;

Do I understand it right PageFactory is deprecated now ? Is it the reason? What can I use instead? Can somebody give me a link, advice, please


Solution

  • You're correct - Selenium "PageFactory" is deprecated as of v3.11:

    https://ultimateqa.com/selenium-3-11-released/

    PageFactory in C# is deprecated as of version 3.11. This is actually a great change because it prevents usage of a class that is not recommended by the Selenium contributors. Furthermore, not using PageFactory will prevent users from many weird element exceptions that aren’t experienced when using a simple runtime element locator.

    The link continues:

    This in no way means that you should stop using Page Objects Pattern. This is totally a separate concept. You can use Page Object Pattern without the PageFactory.cs. The latter is just a Selenium implementation that has no relation with a design pattern.

    Finally:

    Avoiding PageFactory is very simple using Acceptance Test Driven Automation. Here’s an example of a class that meets all Page Object best practices:

    public class ProductsPage : BasePage
    {
        private readonly string _pageUrlPart;
    
        public ProductsPage(IWebDriver driver) : base(driver)
        {
            _pageUrlPart = "inventory.html";
        }
    
        // An element can be located using ExpectedConditions through an explicit wait
        public bool IsLoaded => Wait.UntilIsDisplayedById("inventory_filter_container");
    
        //elements are not accessible for the external test API
        private IWebElement LogoutLink => _driver.FindElement(By.Id("logout_sidebar_link"));
    
        // An element can also be located without ExpectedConditions
        private IWebElement HamburgerElement => _driver.FindElement(By.ClassName("bm-burger-button"));
    
        public int ProductCount =>
            _driver.FindElements(By.ClassName("inventory_item")).Count;
    
        //We are using Composition to have one page object living in another page object
        public CartComponent Cart => new CartComponent(_driver);
    
        public void Logout()
        {
            HamburgerElement.Click();
            LogoutLink.Click();
        }
    }