0

Basically, I would like to make an assertion (from my test class) that a WebElement contains text(). Since all of my WebElements are defined in my page.class, I think I have to make them public to do this.

I am running into a few problems with the webdriver and elements, and I think it may be because multiple test classes are accessing WebElements from the page class simultaneously. My question is: Is there a reason the WebElements must be private?

Code example:

All PageFactory tutorials I have seen say to make your WebElements private, like

    @FindBy(xpath = "//*[@id='searchStringMain']")
    private WebElement searchField;

But to assert that an element contains text (from another class), I have to define them like this:

    @FindBy(xpath = "(//*[contains (text(),'Hrs')])[2]")
    public static WebElement yourLoggedTime;
1
  • The purpose of PageObjects is to encapsulate details about page elements. If you made them public then when (not if) one of them changed you would have to hunt down all the places you referenced it and duplicate the change. By encapsulating web elements in a page object you change it once. Your tests should care about behavior (e.g. searchFor) not the details about which elements were manipulated. Element details are only to be found in PageObjects. Commented Nov 18, 2016 at 21:08

2 Answers 2

1

Consider this example:

package org.openqa.selenium.example;

import org.openqa.selenium.By;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.WebElement;

public class GoogleSearchPage {
    // The element is now looked up using the name attribute
    @FindBy(how = How.NAME, using = "q")
    private WebElement searchBox;


    public void searchFor(String text) {
        // We continue using the element just as before
        searchBox.sendKeys(text);
        searchBox.submit();
    }
}

searchbox is private but the method searchFor is public. The test would use searchFor but never searchBox.

I usually put the page factory initElements call in the last line of the page constructor. This makes all the public functions available to the tests. So

package org.openqa.selenium.example;

import org.openqa.selenium.By;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
import org.openqa.selenium.WebElement;

public class GoogleSearchPage {
    public WebDriver driver;
    // The element is now looked up using the name attribute
    @FindBy(how = How.NAME, using = "q")
    private WebElement searchBox;

    public GoogleSearchPage(WebDriver driver) {
        this.driver = driver
        PageFactory.initElements(driver, this);
    }


    public void searchFor(String text) {
        // We continue using the element just as before
        searchBox.sendKeys(text);
        searchBox.submit();
    }
}

In your test you can do something like:

new GoogleSearchPage(webDriver).searchFor("Foo");
Sign up to request clarification or add additional context in comments.

1 Comment

Do we also need to create methods for click, clear, sendkeys etc which is already provided by Selenium api? If we use the public access modifier we can get clear/click,sendKeys etc in test files directly.What ie your opinion?
0

You can keep your class filed public but as a standard practice it is advised to have getter method for class filed rather than direct filed access.
Problem is static keyword you are using with public. When you are using @FindBy annotation with filed (webelement), it initialize at the time when class initialize (or depending on your implementation where initElements() called). So it is fine to have webelement public but not static. For instance:

In your page class:

@FindBy(xpath = "(//*[contains (text(),'Hrs')])[2]")
public WebElement yourLoggedTime;

In test:

String yourLoggedTime = pageObj.yourLoggedTime.getText(); //pageObj is object of your page class

1 Comment

Breaks encapsulation by exposing WebElements which could matter if yourLoggedTime is used in many tests. I would rather have a page object method that describes a behavior and returns a string but I suppose that it is a matter of taste.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.