Page Object – поширений design pattern, під час написання автоматичних тестів для WEB UI. Суть полягає у відокремленні коду низькорівневої логіки взаємодії зі сторінками тестованого додатку, від коду логіки тестів:
- для кожної сторінки створюється окремий клас, котрий інкапсулює опис елементів (локатори) та методи для взаємодії з елементами
- тести взаємодіють зі сторінками тільки через об’єкти класів сторінок
- завдяки тому, що сторінка описується тільки в одному місці, зменшується дублювання коду, полегшується підтримка, в разі зміни локатора або логіки взаємодії зі сторінкою
В цій нотатці я створю простий приклад Page Object з використанням бібліотеки Selenide. Ознайомлювальна з бібліотекою нотатка доступна за посиланням:
Selenide – простий приклад написання автотесту
Кроки тесту:
- Відкрити сторінку авторизації на демо сайті за адресою https://demoqa.com/login
- Ввести коректні дані користувача та натиснути Login
- Після авторизації, на сторінці профілю перевірити відображення username (в цьому вигаданому тесті, саме це буде вважатися успішною авторизацією)

Реалізація
Клас User, звичайний Value Object, з полями username та password, значення котрих будуть використовуватись для авторизації:
package wiki.it.notes.selenide.pageobject.bookstore.models;
public record User(String username, String password) {}Клас LoginPage, містить поля з локаторами елементів форми для авторизації та метод loginToProfile:
package wiki.it.notes.selenide.pageobject.bookstore.pages;
import wiki.it.notes.selenide.pageobject.bookstore.models.User;
import static com.codeborne.selenide.Selenide.*;
public class LoginPage {
public final static String URL = "login";
private final String USERNAME_FIELD = "#userName";
private final String PASSWORD_FIELD = "#password";
private final String LOGIN_BUTTON = "#login";
public ProfilePage loginToProfile(User user) {
$(USERNAME_FIELD).setValue(user.username());
$(PASSWORD_FIELD).setValue(user.password());
$(LOGIN_BUTTON).click();
return page(ProfilePage.class);
}
}Слід звернути увагу, що метод loginToProfile, після виконання котрого ми повинні опинитися на сторінці профілю, одразу повертає об’єкт сторінки ProfilePage.
Клас ProfilePage містить метод getUsername, для отримання тексту з елементу, котрий відображає username користувача:
package wiki.it.notes.selenide.pageobject.bookstore.pages;
import static com.codeborne.selenide.Selenide.$;
public class ProfilePage {
public final static String URL = "profile";
private final String USERNAME_VALUE = "#userName-value";
public String getUsername() {
return $(USERNAME_VALUE).text();
}
}Базовий тестовий клас містить метод setupSuite, де задається базовий url:
package wiki.it.notes.selenide.pageobject.bookstore;
import com.codeborne.selenide.Configuration;
import org.testng.annotations.BeforeSuite;
public abstract class BaseTest {
@BeforeSuite
void setupSuite() {
Configuration.baseUrl = "https://demoqa.com/";
}
}Клас LoginTest з тестом successLoginTest:
package wiki.it.notes.selenide.pageobject.bookstore;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import wiki.it.notes.selenide.pageobject.bookstore.models.User;
import wiki.it.notes.selenide.pageobject.bookstore.pages.LoginPage;
import static com.codeborne.selenide.Selenide.open;
import static org.assertj.core.api.Assertions.assertThat;
public class LoginTest extends BaseTest {
private User user;
@BeforeClass
void setupClass() {
user = new User("it-notes", "Aqa12345*");
}
@Test
void successLoginTest() {
var profilePage = open(LoginPage.URL, LoginPage.class).loginToProfile(user);
assertThat(profilePage.getUsername())
.as("Check username on profile page")
.isEqualTo(user.username());
}
}Взаємодія тесту зі сторінками сайту відбувається через об’єкти Page класів. В якості assert використовується бібліотека assertJ.
Код з нотатки можна також побачити на GitHub:
Selenide page object simple example