Selenide для начинающих: полный гайд по автоматизации тестирования в 2026
Изучаем Selenide с нуля: установка, первые тесты, Page Object Model, Container, кастомные проверки, работа с элементами. Практический туториал для Java QA Automation.
Что такое Selenide и зачем он нужен
Selenide — это обёртка над Selenium WebDriver, которая упрощает написание UI-автотестов на Java. Основные преимущества: автоматические ожидания, читаемый синтаксис, встроенные скриншоты при падении тестов, богатая библиотека проверок.
Установка и настройка Selenide
Добавьте зависимости в pom.xml:
1<dependencies>
2 <dependency>
3 <groupId>com.codeborne</groupId>
4 <artifactId>selenide</artifactId>
5 <version>7.0.4</version>
6 <scope>test</scope>
7 </dependency>
8 <dependency>
9 <groupId>org.junit.jupiter</groupId>
10 <artifactId>junit-jupiter</artifactId>
11 <version>5.10.1</version>
12 <scope>test</scope>
13 </dependency>
14</dependencies>Первый тест на Selenide
1import static com.codeborne.selenide.Selenide.*;
2import static com.codeborne.selenide.Condition.*;
3
4@Test
5public void loginTest() {
6 open("https://example.com/login");
7 $("#email").setValue("user@example.com");
8 $("#password").setValue("password");
9 $("button[type=submit]").click();
10 $("h1").shouldHave(text("Dashboard"));
11}Основные методы работы с элементами
1@Test
2public void elementsInteraction() {
3 open("https://example.com");
4
5 // Поиск элементов
6 $("#id").click(); // по ID
7 $(".class-name").setValue("text"); // по CSS-классу
8 $("[data-test=button]").click(); // по атрибуту
9 $(byText("Click me")).click(); // по тексту
10 $(byTitle("Tooltip")).hover(); // по title
11
12 // Работа с коллекциями
13 $$("li").shouldHave(size(5)); // размер коллекции
14 $$("li").first().click(); // первый элемент
15 $$("li").last().shouldBe(visible); // последний элемент
16 $$("li").get(2).click(); // элемент по индексу
17
18 // Проверки состояния
19 $("#button").shouldBe(visible);
20 $("#input").shouldBe(enabled);
21 $("#checkbox").shouldBe(checked);
22 $("#element").shouldHave(text("Expected text"));
23 $("#element").shouldHave(attribute("class", "active"));
24}Кастомные проверки (Custom Conditions)
Selenide позволяет создавать собственные проверки для специфичной бизнес-логики. Это делает тесты более читаемыми и переиспользуемыми.
1// CustomConditions.java
2import com.codeborne.selenide.Condition;
3import com.codeborne.selenide.Driver;
4import org.openqa.selenium.WebElement;
5
6public class CustomConditions {
7
8 // Проверка, что элемент содержит только цифры
9 public static Condition onlyDigits = new Condition("only digits") {
10 @Override
11 public boolean apply(Driver driver, WebElement element) {
12 String text = element.getText();
13 return text.matches("\\d+");
14 }
15 };
16
17 // Проверка, что элемент имеет определённый CSS-стиль
18 public static Condition hasBackgroundColor(String expectedColor) {
19 return new Condition("background-color " + expectedColor) {
20 @Override
21 public boolean apply(Driver driver, WebElement element) {
22 String actualColor = element.getCssValue("background-color");
23 return actualColor.equals(expectedColor);
24 }
25 };
26 }
27
28 // Проверка, что элемент содержит валидный email
29 public static Condition validEmail = new Condition("valid email") {
30 @Override
31 public boolean apply(Driver driver, WebElement element) {
32 String text = element.getText();
33 return text.matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");
34 }
35 };
36
37 // Проверка, что элемент находится в viewport
38 public static Condition inViewport = new Condition("in viewport") {
39 @Override
40 public boolean apply(Driver driver, WebElement element) {
41 return (Boolean) driver.executeJavaScript(
42 "var rect = arguments[0].getBoundingClientRect();" +
43 "return rect.top >= 0 && rect.left >= 0 && " +
44 "rect.bottom <= window.innerHeight && " +
45 "rect.right <= window.innerWidth;", element);
46 }
47 };
48}Использование кастомных проверок в тестах:
1@Test
2public void customConditionsTest() {
3 open("https://example.com");
4
5 $("#phone-number").shouldHave(CustomConditions.onlyDigits);
6 $("#error-message").shouldHave(CustomConditions.hasBackgroundColor("rgb(255, 0, 0)"));
7 $("#email-field").shouldHave(CustomConditions.validEmail);
8 $("#important-element").shouldBe(CustomConditions.inViewport);
9}Container — группировка элементов
Container позволяет группировать связанные элементы в логические блоки. Это особенно полезно для повторяющихся компонентов: карточек товаров, форм, модальных окон.
1// ProductCard.java
2import com.codeborne.selenide.Container;
3import com.codeborne.selenide.SelenideElement;
4
5public class ProductCard implements Container {
6 private final SelenideElement self;
7
8 public ProductCard(SelenideElement self) {
9 this.self = self;
10 }
11
12 @Override
13 public SelenideElement getSelf() {
14 return self;
15 }
16
17 // Элементы карточки товара
18 public SelenideElement title() {
19 return self.$("h3.product-title");
20 }
21
22 public SelenideElement price() {
23 return self.$(".price");
24 }
25
26 public SelenideElement addToCartButton() {
27 return self.$(".add-to-cart");
28 }
29
30 public SelenideElement image() {
31 return self.$(".product-image img");
32 }
33
34 public SelenideElement rating() {
35 return self.$(".rating");
36 }
37
38 // Бизнес-методы
39 public ProductCard addToCart() {
40 addToCartButton().click();
41 return this;
42 }
43
44 public String getTitle() {
45 return title().getText();
46 }
47
48 public String getPrice() {
49 return price().getText();
50 }
51
52 public boolean isInStock() {
53 return !self.$(".out-of-stock").exists();
54 }
55}1// UserProfileForm.java
2public class UserProfileForm implements Container {
3 private final SelenideElement self;
4
5 public UserProfileForm(SelenideElement self) {
6 this.self = self;
7 }
8
9 @Override
10 public SelenideElement getSelf() {
11 return self;
12 }
13
14 public SelenideElement firstNameField() {
15 return self.$("#firstName");
16 }
17
18 public SelenideElement lastNameField() {
19 return self.$("#lastName");
20 }
21
22 public SelenideElement emailField() {
23 return self.$("#email");
24 }
25
26 public SelenideElement saveButton() {
27 return self.$(".save-button");
28 }
29
30 public SelenideElement cancelButton() {
31 return self.$(".cancel-button");
32 }
33
34 // Бизнес-методы
35 public UserProfileForm fillForm(String firstName, String lastName, String email) {
36 firstNameField().setValue(firstName);
37 lastNameField().setValue(lastName);
38 emailField().setValue(email);
39 return this;
40 }
41
42 public void save() {
43 saveButton().click();
44 }
45
46 public void cancel() {
47 cancelButton().click();
48 }
49}Page Object Model с Selenide
Page Object Model — основной паттерн для структурирования UI-тестов. В Selenide он реализуется особенно элегантно благодаря встроенной поддержке.
1// LoginPage.java
2import com.codeborne.selenide.SelenideElement;
3import static com.codeborne.selenide.Selenide.$;
4import static com.codeborne.selenide.Selenide.page;
5
6public class LoginPage {
7 private final SelenideElement emailField = $("#email");
8 private final SelenideElement passwordField = $("#password");
9 private final SelenideElement loginButton = $("button[type=submit]");
10 private final SelenideElement errorMessage = $(".error-message");
11 private final SelenideElement forgotPasswordLink = $(".forgot-password");
12
13 // Методы взаимодействия
14 public LoginPage enterEmail(String email) {
15 emailField.setValue(email);
16 return this;
17 }
18
19 public LoginPage enterPassword(String password) {
20 passwordField.setValue(password);
21 return this;
22 }
23
24 public DashboardPage clickLogin() {
25 loginButton.click();
26 return page(DashboardPage.class);
27 }
28
29 public LoginPage clickForgotPassword() {
30 forgotPasswordLink.click();
31 return this;
32 }
33
34 // Методы проверки
35 public LoginPage shouldHaveErrorMessage(String expectedMessage) {
36 errorMessage.shouldHave(text(expectedMessage));
37 return this;
38 }
39
40 public LoginPage shouldBeOpened() {
41 loginButton.shouldBe(visible);
42 return this;
43 }
44
45 // Комплексные методы
46 public DashboardPage loginAs(String email, String password) {
47 return enterEmail(email)
48 .enterPassword(password)
49 .clickLogin();
50 }
51}1// DashboardPage.java
2public class DashboardPage {
3 private final SelenideElement welcomeMessage = $("h1.welcome");
4 private final SelenideElement userMenu = $(".user-menu");
5 private final SelenideElement logoutButton = $(".logout");
6 private final SelenideElement notificationsPanel = $(".notifications");
7
8 public DashboardPage shouldBeOpened() {
9 welcomeMessage.shouldBe(visible);
10 return this;
11 }
12
13 public DashboardPage shouldHaveWelcomeMessage(String userName) {
14 welcomeMessage.shouldHave(text("Welcome, " + userName));
15 return this;
16 }
17
18 public LoginPage logout() {
19 userMenu.click();
20 logoutButton.click();
21 return page(LoginPage.class);
22 }
23
24 public int getNotificationsCount() {
25 return notificationsPanel.$$("li").size();
26 }
27}1// ProductCatalogPage.java
2public class ProductCatalogPage {
3 private final ElementsCollection productCards = $$("[data-test=product-card]");
4 private final SelenideElement searchField = $("#search");
5 private final SelenideElement filterButton = $(".filter-button");
6 private final SelenideElement sortDropdown = $("#sort");
7
8 // Работа с Container
9 public ProductCard getProductCard(int index) {
10 return productCards.get(index).as(ProductCard.class);
11 }
12
13 public ProductCard findProductByTitle(String title) {
14 return productCards.asFixedIterable()
15 .stream()
16 .map(element -> element.as(ProductCard.class))
17 .filter(card -> card.getTitle().equals(title))
18 .findFirst()
19 .orElseThrow(() -> new AssertionError("Product not found: " + title));
20 }
21
22 public ProductCatalogPage searchFor(String query) {
23 searchField.setValue(query).pressEnter();
24 return this;
25 }
26
27 public ProductCatalogPage sortBy(String sortOption) {
28 sortDropdown.selectOption(sortOption);
29 return this;
30 }
31
32 public ProductCatalogPage shouldHaveProductsCount(int expectedCount) {
33 productCards.shouldHave(size(expectedCount));
34 return this;
35 }
36}Использование Page Object в тестах
1public class LoginTest {
2
3 @Test
4 public void successfulLogin() {
5 open("https://example.com/login");
6
7 new LoginPage()
8 .shouldBeOpened()
9 .loginAs("user@example.com", "password")
10 .shouldBeOpened()
11 .shouldHaveWelcomeMessage("John Doe");
12 }
13
14 @Test
15 public void loginWithInvalidCredentials() {
16 open("https://example.com/login");
17
18 new LoginPage()
19 .enterEmail("invalid@example.com")
20 .enterPassword("wrongpassword")
21 .clickLogin()
22 .shouldHaveErrorMessage("Invalid credentials");
23 }
24
25 @Test
26 public void productCatalogTest() {
27 open("https://example.com/catalog");
28
29 ProductCatalogPage catalogPage = new ProductCatalogPage();
30
31 catalogPage
32 .searchFor("laptop")
33 .shouldHaveProductsCount(5)
34 .sortBy("Price: Low to High");
35
36 ProductCard firstProduct = catalogPage.getProductCard(0);
37 firstProduct
38 .addToCart()
39 .title().shouldHave(text("Gaming Laptop"));
40
41 ProductCard specificProduct = catalogPage.findProductByTitle("MacBook Pro");
42 specificProduct.addToCart();
43 }
44}Работа с формами и валидацией
1@Test
2public void userProfileFormTest() {
3 open("https://example.com/profile");
4
5 UserProfileForm profileForm = $("#profile-form").as(UserProfileForm.class);
6
7 profileForm
8 .fillForm("John", "Doe", "john.doe@example.com")
9 .save();
10
11 // Проверяем, что форма сохранилась
12 $(".success-message").shouldHave(text("Profile updated successfully"));
13
14 // Проверяем кастомными условиями
15 profileForm.emailField().shouldHave(CustomConditions.validEmail);
16}Конфигурация Selenide
1@BeforeAll
2static void setUp() {
3 Configuration.browser = "chrome";
4 Configuration.browserSize = "1920x1080";
5 Configuration.headless = false;
6 Configuration.timeout = 10000;
7 Configuration.pageLoadTimeout = 30000;
8 Configuration.screenshots = true;
9 Configuration.savePageSource = false;
10 Configuration.reportsFolder = "target/selenide-reports";
11}
12
13@AfterEach
14void tearDown() {
15 closeWebDriver();
16}Лучшие практики Selenide
- ▸Используйте Page Object Model для структурирования тестов
- ▸Группируйте связанные элементы в Container
- ▸Создавайте кастомные проверки для специфичной бизнес-логики
- ▸Используйте fluent API для читаемости тестов
- ▸Не забывайте про автоматические ожидания — избегайте Thread.sleep()
- ▸Настраивайте глобальную конфигурацию один раз
- ▸Используйте встроенные скриншоты для отладки
Заключение
Selenide предоставляет мощные инструменты для создания поддерживаемых UI-тестов. Комбинация Page Object Model, Container и кастомных проверок позволяет создавать читаемые и надёжные автотесты. На курсах ThreadQA по Java QA Automation Selenide изучается как основной инструмент для UI-тестирования.