1

I am building a testing framework for a website using Page Object Model with Selenium

I am thinking that in general if I have two pages with the exact user controls and functions but different URLs I should create one father page class that has two classes inheriting from it. But what if I have the same two pages with different locators for controls? what do you think? do you think that creating a totally separate class for every page will be a good practice? or is there a way to let the children classes override locators? knowing that I am using PageFactory.

Here is an example:

public class Header 
    {
    [FindsBy(How = How.ClassName, Using = "logout_button")]
    public IWebElement BtnLogout { get; set; }
    public Header()
     {
      PageFactory.InitElements(Browser.Driver, this);
     }

    public void Logout()
     {
      this.BtnLogout.Click();
     }
    }

public class Header 
{
    [FindsBy(How = How.ClassName, Using = "logout")]
    public IWebElement BtnLogout { get; set; }

   public Header()
    {
     PageFactory.InitElements(Browser.Driver, this);
    }

   public void Logout()
   {
    this.BtnLogout.Click();
   }
}
  • correct you about what? – Yahya Hussein Dec 27 '16 at 7:29
  • Why same page has different locators? What is the thing this locator depend on? – dzieciou Dec 27 '16 at 12:05
  • no, I am assuming that the website has pages with the same content, it is not the same page, different pages with the same content – Yahya Hussein Dec 27 '16 at 12:07
  • So it looks like they provide similar functionality, e.g. function to logout, but implemented differently. Looks like a good place for interfaces. See my answer. – dzieciou Dec 27 '16 at 12:09
1

I don't know about C# but in Java annotations are static and cannot be changed at runtime. So this excludes using PageFactory.

However, you could simply use dynamic locators, i.e., old driver.findElement(locator) where locator is provided somehow dynamically. This doesn't seem very clear implementation to me. Neither I can see any benefit from that.

More clear solution for me would be to involve interface, e.g.,

public interface Header {
   void Logout();
}

public class Header1 implements Header { 

    [FindsBy(How = How.ClassName, Using = "logout")]
    public IWebElement BtnLogout { get; set; }

    public Header1() {
      PageFactory.InitElements(Browser.Driver, this);
    }

   @Override
   public void Logout() {
    this.BtnLogout.Click();
   }
}

public class Header2 implements Header { 

    [FindsBy(How = How.ClassName, Using = "logout_button")]
    public IWebElement BtnLogout { get; set; }

    public Header2() {
      PageFactory.InitElements(Browser.Driver, this);
    }

   @Override
   public void Logout() {
    this.BtnLogout.Click();
   }
}

And can be used:

Header oneHeader = new Header1();
Header anotherHeader = new Header2();
...
oneHeader.Logout();
...
anotherHeader.Logout();
  • so you are suggesting that I should get rid off the FindsBy annotations ? and not use PageFactory? – Yahya Hussein Dec 27 '16 at 12:15
  • @YahyaHHussein Yes if you see a benefit of using interfaces. It obviously depends on your use case. – dzieciou Dec 27 '16 at 12:16
  • yes, you are right, it depends on the system I am testing, but is getting rid off Pagefactory is a good practice? it is a cheap price to pay to buy more organised architecture? I am thinking about this trade, what do you think? – Yahya Hussein Dec 27 '16 at 12:19
  • @YahyaHHussein I re-thought and think that PageFactory with annotations still can be used. See my update to the answer. – dzieciou Dec 27 '16 at 12:27
  • 1
    I am new in the company, so I am working on it, thanks :) – Yahya Hussein Dec 27 '16 at 12:53
1

One more suggestion which doesn't need separate objects. Might be useful if your locators are different because of, let's say, different user roles, and you want to stick with PageFactory.

Use

[FindsBy(How = How.Xpath, 
       Using = "@class='logout' or @class='logoutbutton']")] 
public IWebElement BtnLogout { get; set; }

Duplicating objects just because you need to change one selector is bad. Unless there is a very good reason for it. You can abstract Header, but it wouldn't change the fact that there is a code duplication.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.