Using PageObjects, Page Factory, and WebDriverWait in Selenium WebDriver using Java

I use Selenium WebDriver to implement functional tests for some of the projects I worked with. I am trying to use a page object design template with a Factory page to separate my locators. I also created a static WaitTool (singleton) object that implements several wait methods with additional timeout parameters.

My current problem is that I would like to use my wait methods before PageFactory tries to initialize WebElements. The reason I want to wait is because PageFactory might try to initialize page elements before they are available on the page.

Here is an example PageObject:

public class SignInPage extends PageBase { @FindBy(id = "username") @CacheLookup private WebElement usernameField; @FindBy(id = "password") @CacheLookup private WebElement passwordField; @FindBy(name = "submit") @CacheLookup private WebElement signInButton; public SignInPage(WebDriver driver) { super(driver); WaitTool.waitForPageToLoad(driver, this); // I'd like initialisation to occur here } public MainPage signInWithValidCredentials(String username, String password){ return signIn(username, password, MainPage.class); } private <T>T signIn(String username, String password, Class<T> expectedPage) { usernameField.type(username); passwordField.type(password); signInButton.click(); return PageFactory.initElements(driver, expectedPage); } } 

Here is an example of TestObject:

 public class SignInTest extends TestBase { @Test public void SignInWithValidCredentialsTest() { SignInPage signInPage = PageFactory.initElements(driver, SignInPage.class); MainPage mainPage = signInPage.signInWithValidCredentials("sbrown", "sbrown"); assertThat(mainPage.getTitle(), is(equalTo(driver.getTitle()))); } } 

I try to put my logic in the page object (including expectations) as much as possible, as this makes the test cases more readable.

+4
source share
1 answer

The WebElements in the PageFactroy file are indeed proxies for WebElements. This means that every time you access the WebElement, it searches to find the element on the page.

This has some advantages:

  • When PageFactory is initialized, the proxy is configured, but WebElements are not found at this point (so you will not get a NoSuchElementException)
  • Every time you use WebElement, it will go and find it again, so you should not use StaleElementException

You use the @CacheLookup annotation, which will lose your second advantage, since it will find the item once and then keep the link to it, now you will see StaleElementExceptions much more often.

At the same time, you still retain the main advantage that Selenium will not go to the page and will not find the element until you start using it.

So all you have to do is move

 PageFactory.initElements(driver, this); 

In your constructor, and everything will work well.

+7
source

All Articles