Page Factory
Проблема
Классический Page Object Model требует явно вызывать driver.findElement(By.id("...")) каждый раз при обращении к элементу. Это многословно: для страницы с 10 элементами нужно 10 полей с явной инициализацией в конструкторе. Кроме того, если элемент инициализируется в конструкторе, а страница ещё не загрузилась — тест сразу упадёт с NoSuchElementException, даже если элемент появится через секунду.
Page Factory — это усовершенствование POM, встроенное в Selenium. Аннотация @FindBy декларативно описывает локатор прямо над полем. Метод PageFactory.initElements() откладывает поиск элемента до момента первого обращения к нему (ленивая инициализация через прокси). Код страницы становится компактнее, а риск StaleElementReferenceException снижается, так как элемент заново ищется при каждом обращении.
Структура модуля
page-factory/
├── build.gradle
└── src/
└── test/
└── java/
└── dev/shipovalov/pagefactory/
├── GoogleSearchPage.java # Page Object с @FindBy-аннотациями
├── GoogleResultsPage.java # Page Object результатов с @FindBy
└── PageFactoryTest.java # Тест, демонстрирующий Page Factory
Ключевые классы
| Класс | Назначение |
|---|---|
GoogleSearchPage |
Поля помечены @FindBy, в конструкторе вызывается PageFactory.initElements(driver, this)
|
GoogleResultsPage |
Аналогично — элементы результатов через @FindBy(css = "...")
|
PageFactoryTest |
Тест, сравнивающий подход с явным findElement и с @FindBy
|
Сравнение подходов
// Классический POM — явный поиск при каждом использовании
public class SearchPagePOM {
private WebDriver driver;
public void search(String query) {
driver.findElement(By.name("q")).sendKeys(query);
driver.findElement(By.name("btnK")).click();
}
}
// Page Factory — декларативные аннотации, ленивая инициализация
public class SearchPageFactory {
@FindBy(name = "q")
private WebElement searchInput;
@FindBy(name = "btnK")
private WebElement searchButton;
public SearchPageFactory(WebDriver driver) {
PageFactory.initElements(driver, this);
}
public void search(String query) {
searchInput.sendKeys(query);
searchButton.click();
}
}
Запуск тестов
./gradlew :page-factory:test
Отчёт о результатах: page-factory/build/reports/tests/test/index.html