В этой статье я бы хотел поделиться своим опытом автоматизации функционального тестирования. Речь пойдет о написании удобного и надежного тестового фреймворка.
Что будем использовать: 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/
Добавить комментарий