0

I'm having a bit of a hard time designing my page object. What sort of methods should be in there?

Should I put wrapper methods for driver functionalities (e.g driver.findElement(...)) or shall I create a method that does all of these things: create Select, select by index, etc... ?

That way, in the actual test class, I won't have multiple lines, and just call a method.

  • Have you gone through these links, they will guide you how to design page objects. artoftesting.com/automationTesting/pageObjectModel.html guru99.com/… – Dhiman Aug 14 '15 at 20:10
  • @Dhiman Yes, I do do that. I was talking about situations where I need to find an element. Would it be better to have wrapper methods instead of keep doing "driver.findElement()" and have multiple lines of code in the test class. Also, the Assert.assertEquals(), that should go in the test class, or page object? Again, should there be a wrapper method for Asserts? – yob-v-u Aug 14 '15 at 20:31
  • 1
    See martinfowler.com/bliki/PageObject.html. – user246 Aug 15 '15 at 16:46
1

Page objects can be flexible and should reflect the way you write and maintain your tests. For myself, I typically keep my page objects as compact and stateless as possible.

If your pages have a lot of re-usable components, you can put those into smaller classes that encapsulate that functionality independently, then you can use composition to integrate it into any page object that requires it's features. This can reduce the clutter of what can feel like an unwieldy sized page object.

In terms of element management, you could write a container class that accepts a CSS selector or XPath and can get you elements on call. You can also store the selectors as instance fields in your page object to be used on command in your methods to get WebElements exactly when they're needed.

The methods you write for your page object should not reveal the inner WebDriver workings to the test and test writer. If an element can be typed into and read from. It would be better to have two methods perform those explicit actions than it would be to expose the WebDriver layer and return a WebElement or other WebDriver object.

One of the best strengths of the page object model in my opinion is that it creates a total separation between the test layer and WebDriver layer in your code.

0

The code that orcestrates your code shouldn't be interacting with selenium. Neither should it be interacting with thin wrappers for selenium activities. You should create page objects that should appear from the outside to simply do the thing the page should do.

It's important to no expose the internal detail of how your selenium works (which is why my IWebElements are always private). Here's a simplified example of a page with a form that adds a 'foo'. Notice I'm not clicking buttons from outside, I'm simply adding a 'foo' and letting the CreateFooPage encapsulate the messy details of how I do that. Similarly, if I had a page with a table of 'Foos' I would create a page that exposed a Collection<Foo> rather than any table related detail.

public class CreateFooPage
{
    public CreateFooPage(IWebDriver webDriver)
    {
          Driver = webDriver;
    }

    private IWebDriver Driver { get; set; }

    private IWebElement NameTextBox
    {
        get
        {
            return Driver.FindElement(By.Id("Name"));
        }
    }

    private IWebElement SaveButton
    {
        get
        {
            return Driver.FindElement(By.Id("save-button"));
        }
    }

    // How I expose the creeate functionality
    public void CreateFoo(string name)
    {
        NameTextBox.Clear();

        NameTextBox.SendKeys(name);

        SaveButton.Click();
    }

    // How I would expose a table of elements
    public IEnumerable<Foo> Foos
    {
         get { throw new NotImpelementedException(); }
    }
}

The test code can now be free of Selenium code. It can do it's job of ochestrating and asserting, for example

 public void I_can_add_a_foo(){
      string name = "bar";
       _site.CurrentPageAs<CreateFooPage>.CreateFoo(name);
      Assert.IsTrue(_site.CurrentPageAs<CreateFooPage>.Foos.Any( foo => foo.Name = name));
 }

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.