Простой и удобный шаблон тестового фреймворка на selenide для UI автотестов

от автора

Здравствуйте.

В этой статье я бы хотел поделиться своим опытом автоматизации функционального тестирования. Речь пойдет о написании удобного и надежного тестового фреймворка.

Что будем использовать: Java, Selenide, Alure, TestNG, Maven.


Введение

Проект на GitHub — SelenideBoilerplate.

Часто в статьях по автоматизации тестирования приводятся далекие от реальности примеры, например:

driver.get (“URL”) driver.find_element_by_id(“ID”).send_keys(“username”) driver.find_element_by_id (“ID”).send_keys(“password”) driver.find_element_by_id(“submit”).click() 

Есть много похожих примеров по ожиданиям, page object’ам и т.д. В итоге начинающему тестировщику может быть сложно правильно и удобно все организовать. Проект обрастает костылями из-за чего писать новые тесты и поддерживать старые становится все сложнее.

Также есть некоторые инструменты, которые на мой взгляд слишком многословны и переусложнены.

Я покажу простой, удобный и легко расширяемый тестовый фреймворк, работать с которым гораздо легче чем с обычным selenium и который я успешно использовал на нескольких проектах. Этот проект это основа, на реальных проектах все немного сложнее (паралеллизация, remoteDriver, много тестов и т.д.).

Инструменты

  • Selenide — это библиотека для написания лаконичных и стабильных UI тестов с открытым исходным кодом. Selenide решает большую часть проблем с таймаутами, кликами на элементы которые не успели загрузиться и т.п. Также можно забыть про StaleElementReferenceException. Очень удобный и простой в освоении инструмент, поработав с которым уже не хочется возвращаться к selenium.
  • WebDriverManager — Входит в Selenide. Библиотека которая берет на себя всю работу по скачиваю драйверов для браузера и установке путей к драйверам —
     System.setProperty("webdriver.browser.driver", "/path_to_driver/driver"); 
  • Allure для отчетов.
  • TestNG — тестовый фреймворк.
  • Maven — инструмент для автоматизации сборки проектов.

Структура проекта

Начнем с модулей app и pages.

Класс PageBuilder

Обычно в примерах приводят довольно простые страницы, где все помещается в одном классе. Но на реальных проектах могут быть довольно большие страницы, описывать весь функционал которых в одном классе, не самая лучшая идея. Например это может быть страница пополнения счета с множеством форм разных платежных систем.

В этом случае лучше разбить страницу на несколько классов и даже элементов (например, товар в корзине) и собирать все это вместе в основном классе страницы.

Поэтому лучше создавать все страницы в одном месте, а именно в классе PageBuilder.

package app;  import app.pages.LoginPage;  public class PageBuilder {      public static LoginPage buildLoginPage() {         return new LoginPage("/login");     }      public static BalancePage buildBalancePage() {         DepositForm depositForm = new DepositForm();         WithdrawalForm withdrawalForm = new WithdrawalForm();         return new BalancePage("/balance", depositForm, withdrawalForm);     } }  

Класс AppConfig

В классе AppConfig хранятся настройки тестируемого веб-приложения. Например — адрес сайта, тестовые пользователи и т.п. В этом проекте это просто адрес сайта.

package app;  public class AppConfig {      public static final String baseUrl = "https://google.com";  } 

Класс App

Это главный класс в данном модуле. В конструкторе класса App создаются все страницы.

package app;  import app.pages.LoginPage;  public class App {      public LoginPage loginPage;      public App() {         loginPage = PageBuilder.buildLoginPage();     } } 

Благодаря такому подходу не нужно постоянно создавать page object’ы в тестах, создается только объект App из которого и достаются нужные страницы.

Также в классе App могут быть такие методы как — регистрация, оформление и создание заказа и т.п.

То есть большие операции в которых участвует несколько page object’ов и которые часто нужны в тестах.

Перейдем к page object’ам

Благодаря Selenide работать page object’ами очень просто. Все страницы наследуются от базового класса BasePage. В конструктор page object’а передается относительный url страницы.

Все элементы страницы имеют модификатор доступа public, благодаря чему можно писать тесты как в императивном так и в декларативном стилях. Также из элементов можно доставать необходимые данные, например текст или какой-то атрибут.

Локатор хранится только одном месте. Вся логика страницы должна быть описана в методах страницы.

При таком подходе, если что-то ломается или меняется, в большинстве случаев не нужно переписывать тесты, просто дорабатывается метод или локатор меняется на актуальный.

 package app.pages;  import com.codeborne.selenide.SelenideElement; import helpers.Driver; import static com.codeborne.selenide.Selenide.*;  public class LoginPage extends BasePage {      public SelenideElement loginField = $("#login__username");     public SelenideElement passwordField = $("#login__password");     public SelenideElement signInButton = $("#login_enter");     public SelenideElement termsOfUseLabel = $("label[for=\"login_agree\"]");      public LoginPage(String pageUrl) {         super(pageUrl);     }          public void login(String email, String password) {         loginField.setValue(email);         passwordField.setValue(password);         termsOfUseLabel.click();         signInButton.click();         Driver.waitForUrlContains("account/accounts");     } }  

Остальное

В модуле helpers хранятся 2 важных класса:

TestConfig — Из этого класса можно достать настройки с которыми запускаются тесты. Также здесь указаны настройки по умолчанию.

Тесты запускаются командой mvn test -Dbrowser=chrome -Dheadless=1

Значения переменных достаются из командной строки и благодаря классу TestConfig становятся доступны в тестах и в приложении.

Можно например менять url приложения в зависимости от окружения (dev, stage, production).

 package helpers;  public class TestConfig {      public static String browser = "chrome";     public static String headless = "1";      public static void initConfig() {         browser = System.getProperty("browser") == null ? "chrome" : System.getProperty("browser");         headless = System.getProperty("headless") == null ? "1" : System.getProperty("headless");     }      public static boolean isHeadless() {         return headless.contains("1");     } } 

Класс Driver это моя обертка над selenium и selenide драйверами с парой полезных методов.

Самое важные методы:

Driver.initDriver() — здесь инициализируется драйвер / браузер.

   public static void initDriver() {          // Get settings from command line          TestConfig.initConfig();          // Set settings for selenide browser          Configuration.pageLoadStrategy = "eager";         Configuration.browserSize = "1920x1080";         Configuration.holdBrowserOpen = false;         Configuration.screenshots = false;          if(TestConfig.isHeadless()) {             Configuration.headless = true;         } else {             Configuration.headless = false;         }          switch (TestConfig.browser) {             case "chrome":                 Configuration.browser = Browsers.CHROME;                 break;             case "firefox":                 Configuration.browser = Browsers.FIREFOX;                 break;             default:                 Configuration.browser = Browsers.CHROME;                 break;         }     } 

Driver.clearCookies() Driver.close() 

Тесты

Все тестовые классы наследуются от класса A_BaseTest, в котором создается объект приложения App, логгер, softAssert, открывается и закрывается браузер, очищаются куки после каждого теста.

Также есть A_BaseTestListener в котором можно логировать ошибки.

Тесты выглядят примерно так. Легко читать, легко поддерживать.

import org.testng.annotations.Test;  public class ExampleTest extends A_BaseTest {     @Test     public void loginViaEmail() {         app.loginPage.open();         app.loginPage.login("email@email.com", "passwords");                  logger.info("Sample info message");                         softAssert.assertEquals(2,2);         softAssert.assertAll();     } } 

Тестовые классы указываются в testng.xml.

В папке test-output хранятся логи и скриншоты — Driver.takeScreenshot().

Для отчетов используется Allure. После завершения тестов можно запустить команду allure serve target/allure-results и посмотреть отчет.

Проект на GitHub — SelenideBoilerplate

ссылка на оригинал статьи https://habr.com/ru/post/504408/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *