Использование PageObjects, Page Factory и WebDriverWait в Selenium WebDriver с использованием Java

Я использую Selenium WebDriver для реализации функциональных тестов для некоторых проектов, с которыми я работал. Я пытаюсь использовать шаблон проектирования Page Object с Page Factory, чтобы выделить мои локаторы. Я также создал статический объект WaitTool (singleton), который реализует несколько методов ожидания с необязательными параметрами тайм-аута.

Моя текущая проблема заключается в том, что я хотел бы использовать свои методы ожидания до того, как PageFactory попытается инициализировать WebElements. Причина, по которой я хотел бы подождать, заключается в том, что PageFactory может попытаться инициализировать элементы страницы до того, как они станут доступны на странице.

Вот пример 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);
    }
}

Вот образец 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())));
    }
}

Я стараюсь как можно больше помещать свою логику в объект страницы (включая ожидания), поскольку это делает тестовые примеры более читабельными.


person Jamie Piltz    schedule 24.04.2013    source источник


Ответы (1)


WebElements в PageFactroy на самом деле являются прокси для WebElements. Это означает, что каждый раз, когда вы обращаетесь к WebElement, он будет выполнять поиск, чтобы найти элемент на странице.

У этого есть некоторые преимущества:

  • Когда PageFactory инициализируется, прокси настроены, но в этот момент WebElements не найдены (поэтому вы не получите NoSuchElementException)
  • Каждый раз, когда вы используете WebElement, он будет искать его снова, поэтому вам не следует использовать StaleElementException.

Вы используете аннотацию @CacheLookup, которая лишает вас второго преимущества, поскольку она найдет элемент один раз, а затем сохранит ссылку на него, теперь у вас гораздо больше шансов увидеть StaleElementExceptions.

При этом вы по-прежнему сохраняете главное преимущество, которое заключается в том, что Selenium не переходит на страницу и фактически не находит элемент, пока вы не воспользуетесь им впервые.

Итак, все, что вам нужно сделать, это переместить

PageFactory.initElements(driver, this);

В ваш конструктор, и все будет нормально.

person Ardesco    schedule 24.04.2013
comment
Думаю, это означает, что я не могу вернуть PageFactory.initElements(driver, expectedPage) в функции signIn. - person Jamie Piltz; 26.04.2013
comment
PageFactory.initElements(driver, this.class);, похоже, не работает. однако поставка this или this.getClass() работает, но я не уверен, что это делает то, что я хочу. - person Jamie Piltz; 26.04.2013
comment
Извините, это ошибка в моем ответе. На самом деле я имел в виду именно это (ответ обновлен, чтобы показать правильный фрагмент кода) - person Ardesco; 26.04.2013
comment
Если я правильно вас понимаю, вы просто обеспокоены тем, что при создании экземпляра класса он начнет выдавать ошибку NoSuchElementExcpetion, потому что страница, возможно, не загрузила все WebElements, на которые ссылается PageFactory. Если это вас беспокоит, не беспокойтесь, этого не произойдет. Когда вы выполняете 'PageFactory.initElements (драйвер, это);' в этот момент он настроит все прокси, но не будет пытаться найти элемент на странице, пока вы действительно не воспользуетесь одним из WebElements. - person Ardesco; 26.04.2013
comment
@Ardesco: После того, как я прочитал этот пост и ваши комментарии, у меня возник вопрос. Что в данном случае означают прокси? - person Abhijeet Vaikar; 20.03.2014