Как написать автотест на java

Время на прочтение
12 мин

Количество просмотров 133K

В этой статье рассматривается создание достаточного простого автотеста. Статья будет полезна начинающим автоматизаторам.

Материал изложен максимально доступно, однако, будет значительно проще понять о чем здесь идет речь, если Вы будете иметь хотя бы минимальные представления о языке Java: классы, методы, etc.

Нам понадобятся:

  • установленная среда разработки Intellij IDEA (является самой популярной IDE, для большинства случаев достаточно бесплатной версии Community Edition);
  • установленные Java (jdk/openjdk) и Maven, прописанные в системные окружения ОС;
  • браузер Chrome и chromedriver — программа для передачи команд браузеру.

Создание проекта

Запустим Intellij IDEA, пройдем первые несколько пунктов, касающихся отправки статистики, импорта проектов, выбора цветовой схемы и т.д. — просто выберем параметры по умолчанию.

В появившемся в конце окне выберем пункт «Create New Project», а в нем тип проекта Maven. Окно будет иметь вид:

image

  • Maven — это инструмент сборки Java проектов;
  • Project SDK — версия Java, которая установлена на компьютере;
  • Create from archetype — это возможность создавать проект с определенным архетипом (на данном этапе данный чекбокс отмечать не нужно).

Нажмем «Next». Откроется следующее окно:

image

Groupid и Artifactid — идентификаторы проекта в Maven. Существуют определенные правила заполнения этих пунктов:

  • Groupid — название организации или подразделения занимающихся разработкой проекта. В этом пункте действует тоже правило как и в именовании пакетов Java: доменное имя организации записанное задом наперед. Если у Вас нет своего доменного имени, то можно использовать свой э-мейл, например com.email.email;
  • Artifactid — название проекта;
  • Version — версия проекта.

Нажмем «Finish»: IDE автоматически откроет файл pom.xml:

image

В нем уже появилась информация о проекте, внесенная на предыдущем шаге: Groupid, Artefiactid, Version. Pom.xml — это файл который описывает проект. Pom-файл хранит список всех библиотек (зависимостей), которые используются в проекте.

Для этого автотеста необходимо добавить две библиотеки: Selenium Java и Junit. Перейдем на центральный репозиторий Maven mvnrepository.com, вобьем в строку поиска Selenium Java и зайдем в раздел библиотеки:

image

Выберем нужную версию (в примере будет использована версия 3.14.0). Откроется страница:

image

Копируем содержимое блока «Maven» и вставим в файл pom.xml в блок

<dependencies> </dependencies>

Таким образом библиотека будет включена в проект и ее можно будет использовать. Аналогично сделаем с библиотекой Junit (будем использовать версию 4.12).

Итоговый pom-файл:

image

Создание пакета и класса

Раскроем структуру проекта. Директория src содержит в себе две директории: «main» и «test». Для тестов используется, соответственно, директория «test». Откроем директорию «test», кликом правой клавиши мыши по директории «java» выберем пункт «New», а затем пункт «Package». В открывшемся диалоговом окне необходимо ввести название пакета. Имя базового пакета должно носить тоже имя, что и Groupid — «org.example».

Следующий шаг — создание класса Java, в котором пишется код автотеста. Кликом правой клавиши мыши по названию пакета выберем пункт «New», а затем пункт «Java Class».

В открывшемся диалоговом окне необходимо ввести имя Java класса, например, LoginTest (название класса в Java всегда должно начинаться с большой буквы). В IDE откроется окно тестового класса:

image

Настройка IDE

Прежде чем начать, необходимо настроить IDE. Кликом правой клавиши мыши по названию проекта выберем пункт «Open Module Settings». В открывшемся окне во вкладке «Sources» поле «Language level» по умолчанию имеет значение 5. Необходимо изменить значение поля на 8 (для использования всех возможностей, присутствующих в этой версии Java) и сохранить изменения:

image

Далее необходимо изменить версию компилятора Java: нажмем меню «File», а затем выберем пункт Settings.

В открывшемся перейдем «Build, Execution, Deployment» -> «Compiler» -> «Java Compiler». По умолчанию установлена версия 1.5. Изменим версию на 8 и сохраним изменения:

image

Test Suite

Описание:

  1. Пользователь открывает страницу аутентификации;
  2. Пользователь производит ввод валидных логина и пароля;
  3. Пользователь удостоверяется в успешной аутентификации — об этом свидетельствует имя пользователя в верхнем правом углу окна;
  4. Пользователь осуществляет выход из аккаунта путем нажатия на имя пользователя в верхнем правом углу окна с последующим нажатием на кнопку «Выйти…».

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

Для примера будет использоваться аккаунт Яндекс (учетная запись заранее создана вручную).

Первый метод

В классе LoginTest будет описана логика теста. Создадим в этом классе метод «setup()», в котором будут описаны предварительные настройки. Итак, для запуска браузера необходимо создать объект драйвера:

WebDriver driver = new ChromeDriver();

Перед созданием объекта WebDriver следует установить зависимость, определяющую путь к chomedriver (в ОС семейства Windows дополнительно необходимо указывать расширение .exe):

System.setProperty("webdriver.chrome.driver", "/usr/bin/chromedriver");

Чтобы ход теста отображался в полностью открытом окне, необходимо сказать об этом драйверу:

driver.manage().window().maximaze();

Случается, что элементы на страницах доступны не сразу, и необходимо дождаться появления элемента. Для этого существуют ожидания. Они бывают двух видов: явные и неявные. В примере будет использовано неявное ожидание Implicitly Wait, которое задается вначале теста и будет работать при каждом вызове метода поиска элемента:

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

Таким образом, если элемент не найден, то драйвер будет ждать его появления в течении заданного времени (10 секунд) и шагом в 500 мс. Как только элемент будет найден, драйвер продолжит работу, однако, в противном случае тест упадем по истечению времени.

Для передачи драйверу адреса страницы используется команда:

driver.get("https://passport.yandex.ru/auth")

Выносим настройки

Для удобства вынесем название страницы в отдельный файл (а чуть позже и некоторые другие параметры).

Создадим в каталоге «test» еще один каталог с названием «resources», а в нем обычный файл «conf.properties», в который поместим переменную:

loginpage = https://passport.yandex.ru/auth

а также внесем сюда путь до драйвера

chromedriver = /usr/bin/chromedriver

image

В пакете «org.example» создадим еще один класс «ConfProperties», который будет читать записанные в файл «conf.properties» значения:

image

package org.example;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class ConfProperties {
    protected static FileInputStream fileInputStream;
    protected static Properties PROPERTIES;
    static {
        try {
            //указание пути до файла с настройками
            fileInputStream = new FileInputStream("src/test/resources/conf.properties");
            PROPERTIES = new Properties();
            PROPERTIES.load(fileInputStream);
        } catch (IOException e) {
            e.printStackTrace();
            //обработка возможного исключения (нет файла и т.п.)
        } finally {
            if (fileInputStream != null)
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace(); } } }
    /**
     * метод для возврата строки со значением из файла с настройками
     */
    public static String getProperty(String key) {
        return PROPERTIES.getProperty(key); } }

Обзор первого метода

image

Метод «setup()» пометим аннотацией Junit «@BeforeClass», которая указывает на то, что метод будет выполняться один раз до выполнения всех тестов в классе. Тестовые методы в Junit помечаются аннотацией Test.

package org.example;
import org.junit.BeforeClass;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.concurrent.TimeUnit;
public class LoginTest {
    /**
     * осуществление первоначальной настройки
     */
    @BeforeClass
    public static void setup() {
        //определение пути до драйвера и его настройка
        System.setProperty("webdriver.chrome.driver", ConfProperties.getProperty("chromedriver"));
        //создание экземпляра драйвера
        WebDriver driver = new ChromeDriver();
        //окно разворачивается на полный экран
        driver.manage().window().maximize();
        //задержка на выполнение теста = 10 сек.
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        //получение ссылки на страницу входа из файла настроек
        driver.get(ConfProperties.getProperty("loginpage")); } }

Page Object

При использовании Page Object элементы страниц, а также методы непосредственного взаимодействия с ними, выносятся в отдельный класс.

Создадим в пакете «org.example» класс LoginPage, который будет содержать локацию элементов страницы логина и методы для взаимодействия с этими элементами.

Откроем страницу авторизации в сервисах Яндекс (https://passport.yandex.ru/auth) в браузере Chrome. Для определения локаторов элементов страницы, с которыми будет взаимодействовать автотест, воспользуемся инструментами разработчика. Кликом правой кнопки мыши вызовем меню «Просмотреть код». В появившейся панели нажмем на значок курсора (левый верхний угол панели разработчика) и наведем курсор на интересующий нас элемент — поле ввода логина.

В результате мы увидим этот элемент среди множества других. Теперь мы можем скопировать его локацию. Для этого кликаем правой кнопкой мыши по выделенному в панели разработчика элементу, выбираем меню «Copy» -> «Copy XPath».

//*[@id="root"]/div/div/div[2]/div/div/div[3]/div[2]/div/div/div[1]/form/div[1]/div[1]/label

Для локации элементов в Page Object используется аннотация @FindBy.

Напишем следующий код:

@FindBy(xpath = "//*[@id="root"]/div/div/div[2]/div/div/div[3]/div[2]/div/div/div[1]/form/div[1]/div[1]/label")
private WebElement loginField;

Таким образом мы нашли элемент на страницу и назвали его loginField (элемент доступен только внутри класса LoginPage, т.к. является приватным).

Однако, такой длинный и страшный xpath использовать не рекомендуется (рекомендую к прочтению статью «Не так страшен xpath как его незнание». Если присмотреться, то можно увидеть, что поле ввода логина имеет уникальный id:

image

Воспользуемся этим и изменим поиск элемента по xpath:

@FindBy(xpath = "//*[contains(@id, 'passp-field-login')]")

Теперь вероятность того, что поле ввода пароля будет определено верно даже в случае изменения местоположения элемента на странице, возросла.

Аналогично изучим следующие элементы и получим их локаторы.

Кнопка «Войти»:

@FindBy(xpath = "//*[contains(text(), 'Войти')]")
private WebElement loginBtn;

Поле ввода пароля:

@FindBy(xpath = "//*[contains(@id, 'passp-field-passwd')]")
private WebElement passwdField;

А теперь напишем методы для взаимодействия с элементами.

Метод ввода логина:

public void inputLogin(String login) {
        loginField.sendKeys(login); }

Метод ввода пароля:

public void inputPasswd(String passwd) {
        passwdField.sendKeys(passwd); }

Метод нажатия кнопки входа:

public void clickLoginBtn() {
        loginBtn.click(); }

Для того, чтобы аннотация @FindBy заработала, необходимо использовать класс PageFactory. Для этого создадим конструктор и передадим ему в качестве параметра объект Webdriver:

public WebDriver driver;
public LoginPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
        this.driver = driver; }

image

package org.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class LoginPage {
    /**
     * конструктор класса, занимающийся инициализацией полей класса
     */
    public WebDriver driver;
    public LoginPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
        this.driver = driver; }
    /**
     * определение локатора поля ввода логина
     */
    @FindBy(xpath = "//*[contains(@id, 'passp-field-login')]")
    private WebElement loginField;
    /**
     * определение локатора кнопки входа в аккаунт
     */
    @FindBy(xpath = "//*[contains(text(), 'Войти')]/..")
    private WebElement loginBtn;
    /**
     * определение локатора поля ввода пароля
     */
    @FindBy(xpath = "//*[contains(@id, 'passp-field-passwd')]")
    private WebElement passwdField;
    /**
     * метод для ввода логина
     */
    public void inputLogin(String login) {
        loginField.sendKeys(login); }
    /**
     * метод для ввода пароля
     */
    public void inputPasswd(String passwd) {
        passwdField.sendKeys(passwd); }
    /**
     * метод для осуществления нажатия кнопки входа в аккаунт
     */
    public void clickLoginBtn() {
        loginBtn.click(); } }

После авторизации мы попадаем на страницу пользователя. Т.к. это уже другая страница, в соответствии с идеологией Page Object нам понадобится отдельный класс для ее описания. Создадим класс ProfilePage, в котором определим локаторы для имени пользователя (как показателя успешного входа в учетную запись), а также кнопки выхода из аккаунта. Помимо этого, напишем методы, которые будут получать имя пользователя и нажимать на кнопку выхода.

Итого, страница будет иметь следующий вид:

image

package org.example;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
public class ProfilePage {
    /**
     * конструктор класса, занимающийся инициализацией полей класса
     */
    public WebDriver driver;
    public ProfilePage(WebDriver driver) {
        PageFactory.initElements(driver, this);
        this.driver = driver; }
    /**
     * определение локатора меню пользователя
     */
    @FindBy(xpath = "//*[contains(@class, 'account__name_hasAccentLetter')]")
    private WebElement userMenu;
    /**
     * определение локатора кнопки выхода из аккаунта
     */
    @FindBy(xpath = "//*[contains(@class, 'menu-item_action_exit menu__item menu__item_type_link')]")
    private WebElement logoutBtn;
    /**
     * метод для получения имени пользователя из меню пользователя
     */
    public String getUserName() {
        String userName = userMenu.getText();
        return userName; }
    /**
     * метод для нажатия кнопки меню пользователя
     */
    public void entryMenu() {
        userMenu.click(); }
    /**
     * метод для нажатия кнопки выхода из аккаунта
     */
    public void userLogout() {
        logoutBtn.click(); } }

Интересный момент: в метод getUserName() пришлось добавить еще одно ожидание, т.к. страница «тяжелая» и загружалась довольно медленно. В итоге тест падал, потому что метод не мог получить имя пользователя. Метод getUserName() с ожиданием:

public String getUserName() {
        WebDriverWait wait = new WebDriverWait(driver, 10);
        wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(@class, 'account__name_hasAccentLetter')]")));
        String userName = userMenu.getText();
        return userName; }

Вернемся к классу LoginTest и добавим в него созданные ранее классы-страницы путем объявления статических переменных с соответствующими именами:

public static LoginPage loginPage;
public static ProfilePage profilePage;

Сюда же вынесем переменную для драйвера

public static WebDriver driver;

В аннотации @BeforeClass создаем экземпляры классов созданных ранее страниц и присвоим ссылки на них. Создание экземпляра происходит с помощью оператора new. В качестве параметра указываем созданный перед этим объект driver, который передается конструкторам класса, созданным ранее:

loginPage = new LoginPage(driver);
profilePage = new ProfilePage(driver);

А создание экземпляра драйвера приведем к следующему виду (т.к. он объявлен в качестве переменной):

driver = new ChromeDriver();

Тест

Теперь можно перейти непосредственно к написанию логики теста. Создадим метод loginTest() и пометим его соответствующей аннотацией:

@Test
    public void loginTest() {
        //значение login/password берутся из файла настроек по аналогии с chromedriver
//и loginpage
//вводим логин
        loginPage.inputLogin(ConfProperties.getProperty("login"));
    //нажимаем кнопку входа
        loginPage.clickLoginBtn();
    //вводим пароль
        loginPage.inputPasswd(ConfProperties.getProperty("password"));
    //нажимаем кнопку входа
        loginPage.clickLoginBtn();
        //получаем отображаемый логин
        String user = profilePage.getUserName();
    //и сравниваем его с логином из файла настроек
        Assert.assertEquals(ConfProperties.getProperty("login"), user); }

Осталось лишь корректно все завершить. Создадим финальный метод и пометим его аннотацией @AfterClass (методы помеченные этой аннотацией выполняются один раз, после завершения всех тестовых методов класса).

В этом методе осуществляется вход в меню пользователя и нажатие кнопки «Выйти», чтобы разлогиниться.

@AfterClass
    public static void tearDown() {
        profilePage.entryMenu();
        profilePage.userLogout();
        driver.quit(); }

Последняя строка нужна для закрытия окна браузера.

Обзор теста

Итого, имеем:

package org.example;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.util.concurrent.TimeUnit;
public class LoginTest {
    public static LoginPage loginPage;
    public static ProfilePage profilePage;
    public static WebDriver driver;

    /**
     * осуществление первоначальной настройки
     */
    @BeforeClass
    public static void setup() {
        //определение пути до драйвера и его настройка
        System.setProperty("webdriver.chrome.driver", ConfProperties.getProperty("chromedriver"));
        //создание экземпляра драйвера
        driver = new ChromeDriver();
        loginPage = new LoginPage(driver);
        profilePage = new ProfilePage(driver);
        //окно разворачивается на полный экран
        driver.manage().window().maximize();
        //задержка на выполнение теста = 10 сек.
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        //получение ссылки на страницу входа из файла настроек
        driver.get(ConfProperties.getProperty("loginpage")); }
    /**
     * тестовый метод для осуществления аутентификации
     */
    @Test
    public void loginTest() {
        //получение доступа к методам класса LoginPage для взаимодействия с элементами страницы
        //значение login/password берутся из файла настроек по аналогии с chromedriver
        //и loginpage
        //вводим логин
        loginPage.inputLogin(ConfProperties.getProperty("login"));
        //нажимаем кнопку входа
        loginPage.clickLoginBtn();
        //вводим пароль
        loginPage.inputPasswd(ConfProperties.getProperty("password"));
        //нажимаем кнопку входа
        loginPage.clickLoginBtn();
        //получаем отображаемый логин
        String user = profilePage.getUserName();
        //и сравниваем его с логином из файла настроек
        Assert.assertEquals(ConfProperties.getProperty("login"), user); }
    /**
     * осуществление выхода из аккаунта с последующим закрытием окна браузера
     */
    @AfterClass
    public static void tearDown() {
        profilePage.entryMenu();
        profilePage.userLogout();
        driver.quit(); } }

Запуск автотеста

Для запуска автотестов в Intellij Idea имеется несколько способов:

  • Alt+Shift+F10;
  • Клик правой клавишей мышки по имени тестового класса, после чего в открывшемся меню выбрать Run;

В результате выполнения автотеста, в консоли Idea я вижу, что тестовый метод loginTest() пройден успешно:

image

Как начать писать автотесты на Java

Написать автотест на Java не сложно. Даже без навыков программирования автоматизировать смоук небольшого проекта можно вооружившись знаниями с какого-нибудь мастер-класса.

Трудности начнут появляться по мере роста проекта. Увеличение числа автотестов заставит задуматься об оптимизации скорости их выполнения, организации кода, паттернах проектирования. Сложные кейсы и дальнейшее развитие тестового фреймворка уже потребуют уверенных знаний языка программирования и использования различных библиотек. Чем глубже будет проходить погружение тем с большим количеством технологий придется взаимодействовать, что одновременно и сложно и увлекательно.

Свои первые шаги в автотестах я делал в Яндексе, откуда затем проделал долгий путь до руководителя команды автоматизации тестирования во ВКонтакте, где на момент написания статьи вместе с коллегами развиваю тестовые фреймворки и инструменты для экосистемных проектов VK.

Меня периодически спрашивают «какими знаниями нужно обладать, чтобы начать писать автотесты на Java». В данной статье собрал список того, что считаю полезным со ссылками на материалы для изучения.

Определиться с языком программирования

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

Автотесты можно писать почти на любом языке. Возможно, вы уже знаете какой-либо язык программирования или даже целый стек технологий для автоматизации. Если команда поддержит его и есть уверенность, что в долгосрочной перспективе ваше решение хорошо себя зарекомендует – используйте его.

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

Если у вас уже есть команда автоматизации, и она использует язык отличный от того, на котором написан проект, то возможные проблемы если и имели место быть, то скорее всего решены до вас. Смело выбирайте язык, который использует команда. Преимущества: готовый фреймворк и инфраструктура, наличие экспертов в команде.

Если у вас нет проекта, и вы не знаете какой язык выбрать для изучения, попробуйте обратиться к трендам:

  • TIOBE – рейтинг основан на количестве инженеров работающих с языком, курсов и поисковых запросов из Google, Bing, Yahoo!, Wikipedia, Amazon, YouTube и Baidu.
  • PYPL (PopularitY of Programming Language) – индекс ориентируется на то, как часто в Google ищут учебные материалы по определенному языку.
  • StackOverflow – рейтинг на основе самого популярного форума программистов.
  • Octoverse – рейтинг крупнейшего сервиса для хостинга IT-проектов и совместной разработки.
  • IEEE – рейтинг института инженеров электротехники и электроники.

Вместе с Java в автоматизации тестирования уверенно лидируют Python, JavaScript и С#.

Научиться программировать

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

Ниже представлены ссылки на курсы и книги, которые будут полезны как для изучения Java так и программирования в целом.

Курсы по Java

  • Официальный онлайн учебник по Java от Oracle
  • JavaRush. Один из лучших онлайн-курсов по программированию на Java
  • CodeGym – клон JavaRush на английском языке
  • Java Basics (и другие курсы по Java) от Epam
  • Интерактивный курс по Java от Sololearn
  • Курс Java for Beginners от Hyperskill и JetBrains
  • JavaBegin – fullstack обучение Java/Kotlin для новичков и профессионалов
  • Вопросы для собеседования на Java Developer

Книги по Java

  • Изучаем Java. Бэйтс Берт, Сьерра Кэти
  • Java. Руководство для начинающих. Герберт Шилдт
  • Java для чайников. Барри Бёрд
  • Java. Библиотека профессионала, Кей С. Хорстманн
  • Java. Методы программирования. Романчик Валерий, Блинов Игорь
  • Effective Java. Джошуа Блох
  • Философия Java. Брюс Эккель

Алгоритмы, паттерны и рефакторинг

  • Гарвардский курс «CS50. Основы программирования»
  • leetcode.com – онлайн сервис, где можно практиковаться в решении задач по программированию
  • Грокаем алгоритмы. Иллюстрированное пособие для программистов и любопытствующих
  • Head First. Паттерны проектирования. Эрик Фримен, Берт Бейтс, Кэти Сьерра, Элизабет Робсон
  • Чистый код: создание, анализ и рефакторинг. Роберт Мартин
  • Рефакторинг: улучшение проекта существующего кода. Мартин Фаулер
  • Код. Тайный язык информатики. Чарльз Петцольд
  • Алгоритмы на Java. Роберт Сэджвик, Кэвин Уэйн
  • Книга Погружение в паттерны проектирования, курс Погружение в Рефакторинг и примеры паттернов на GitHub от Александра Швеца, автора сайта Рефакторинг.Гуру. К сожалению сайт заблокирован в России, но доступен под VPN.
  • Статьи на Хабре Пожалуй, лучшая архитектура для UI тестов и Паттерны проектирования в автоматизации тестирования

Познать среду разработки

Писать код можно хоть в блокноте, но лучше использовать IDE (Integrated Development Environment) – интегрированную среду разработки.

Кроме текстового редактора и подсветки синтаксиса, IDE включает в себя инструменты автодополнения команд (autocomplete), предупреждения ошибок, рефакторинга, горячих клавиш (shortcut) и поиска. Встроены компилятор, средства автоматизации сборки, отладчик, терминал, система управления версиями.

IntelliJ IDEA

Несколько лет назад Eclipse и NetBeans довольно часто встречались в качестве рекомендуемых IDE для написания кода на Java. Сейчас их полностью вытеснила IntelliJ IDEA от JetBrains. Бесплатная Community Edition версия работает с Java и Android, которая покрывает потребности для написания автотестов.

В неумелых руках продвинутый инструмент пользы не принесёт. Чтобы использовать IntelliJ IDEA максимально эффективно, изучите её возможности, посмотрите курсы, и важно – выучите шоткаты!

  • Бесплатный курс по IntelliJ IDEA от Хайнца Кабуца
  • Официальное руководство и туториалы по IntelliJ IDEA
  • Канал IntelliJ IDEA от JetBrains на YouTube со множеством полезных гайдов
  • Несколько полезных роликов с Heisenbug про работу в IntelliJ IDEA от Юрия Артамонова: раз, два, три
  • Крутой плагин для изучения шоткатов
  • IntelliJ IDEA Course на YouTube
  • Создание проекта с нуля в IntelliJ IDE
  • IntelliJ IDEA. Профессиональное программирование на Java – книжка аж 2005 года, часть информации устарело, тем не менее пользу извлечь можно, и это единственная книга из известных мне на русском языке.

VS Code

Ещё одна популярная IDE Visual Studio Code так же предоставляет возможности для работы с Java. Если привычнее использовать её, рекомендую изучить официальный java туториал: Getting Started with Java in VS Code и Testing Java with Visual Studio Code.

Прокачать GIT

Работа с кодом, тем более в команде предполагает совместную работу с ним, поэтому умение работать с Git, а вместе с ним GitHub и GitLab – очевидный скилл не только для разработчика, но и любого айтишника, в том числе тестировщика.

Хорошая новость в том, что и IntelliJ IDEA и Visual Studio Code, как и большинство IDE умеют работать с Git через графический интерфейс. Однако, понимание того, что происходит «под капотом», позволит избежать возможных ошибок.

Материалы для изучения Git

Ниже несколько ресурсов для прокачки.

  • Pro Git book – самый популярный учебник по Git
  • Git How To – интерактивный курс
  • Git: наглядная справка – справочник по Git в картинках
  • Git: курс от JavaScript.ru на YouTube – аккуратный, необходимый, слегка «продвинутый»
  • Онлайн-курс «Введение в Git» от Хекслет
  • Learn Git Branching – интерактивный сервис для изучения Git.

Топ 10 команд Git

В повседневной работе с Git используется не так много команд.

Например, команда из примера ниже клонирует репозиторий проекта в текущую папку на компьютере.

git clone https://github.com/адрес-вашего-репозитория

Следующая команда переключится на master – главную ветку проекта.

git checkout master

Команда ниже подтянет из репозитория свежие изменения.

git pull origin master && git fetch

Команда ниже создаст новую ветку в локальном репозитории и переключится, например для новых тестов.

git checkout -b имя-ветки

Такая же команда, но без ключа -b, позволяет переключаться между существующими ветками.

git checkout имя-ветки

Следующая команда добавит все созданные и изменённые файлы в новый коммит.

git commit -a -m имя-коммита

Добавить все созданные и изменённые файлы к отслеживанию Git в текущей ветке, без создания коммита.

git add .

Добавить текщие изменения к текущему, ранее созданному коммиту.

git commit --amend

И последняя команда отправит вашу ветку с текущими коммитами в удалённый репозиторий.

git push --set-upstream origin название-удаленной-ветки

Если обнаружили ошибку, что-то поправили в локальной ветке и нужно по новой сделать пуш следом за отправленным, используйте ключ -f.

git push --set-upstream origin название-удаленной-ветки -f

Разобраться со стеком технологий

Итак, вы умеете программировать (хотя бы немного), как ниндзя применяете шоткаты в IntelliJ IDEA и можете запустить программу на выполнение, а ещё без особых трудностей пушите свой код в удаленный репозиторий и знаете как разрешить конфликты в Git. Если нет – ничего страшного, этому ещё предстоит научиться, но можно двигаться дальше.

Сборщики проектов Gradle и Maven

Современная программа состоит из множества файлов и подключенных библиотек. Если вы уже знакомы с Java то знаете, что прежде чем запустить программу на исполнение, сначала её нужно скомпилировать, превратив в байт код или как говорят «собрать». Ручная сборка проектов на Java – трудоёмкий процесс, чтобы его упростить и автоматизировать, существуют так называемые сборщики проектов.

Помимо непосредственно компиляции проекта, сборщики могут выполнять и другие задачи: запускать тесты, строить отчеты, выполнять очистку временных файлов и другое.

Кроме того, программы редко пишутся с нуля и чаще всего используют сторонние наработки подключаемые в виде пакетов (библиотек) – зависимостей, которые могут хранится локально или располагаться в публичных репозиториях (как у npm в JS или Composer в PHP). Сборщики в том числе умеют управлять этими зависимостями, по-простому – подключать их к проекту. Для этого нужно лишь указать зависимость в конфигурационном файле.

Поиск пакетов для Maven и Gradle от JetBrains

Самые популярные сборщики для Java – Gradle и Maven. В ближайшее время постараюсь сделать небольшую статью по ним. А пока стоит запомнить, что:

  • Функционал Gradle и Maven схож, при выборе сборщика для проекта руководствуйтесь тем что уже используется командой.
  • Gradle популярнее Maven. Однако существует огромное количество проектов на Maven, и популярность не всегда играет решающую роль.
  • Конифг сборки Gradle на Groovy (файл build.gradle), короче XML, используемого в Maven (файл pom.xml).
  • У Gradle нет собственного репозитория, зависимости он загружает из репозитория Maven.
  • Gradle работает быстрее.

Полезные ресурсы по Gradle:

  • Официальный сайт Gradle
  • Документация Gradle
  • Онлайн события и тренинги по Gradle
  • Поиск зависимостей для Gradle

Полезные ресурсы по Maven:

  • Официальный сайт Maven
  • Maven репозиторий

Тестовые фреймворки JUnit и TestNG

Тестовые фреймворки нужны для того, чтобы уметь отделять код автотестов от кода программы (которого может и не быть если проект содержит только тесты), размечать, группировать в сьюты и запускать автотетсы.

Два самых популярных тестовых фреймворка для Java – JUnit и TestNG. Оба сильно схожи по функциональности. Подробное сравнение фреймворков и как подключить их к проекту можно почитать в моей статье JUnit vs TestNG.

JUnit сильно популярнее TestNG, однако как и в случае с Gradle / Maven популярность не всегда играет решающую роль, исходите из своих потребностей и того, что использует команда.

На своем основном проекте во ВКонтакте я использую связку TestNG / Gradle (так исторически сложилось и прекрасно работает), но для новых проектов чаще выбираю стек JUnit / Gradle, если не знаете что использовать, рекомендую попробовать последнее.

  • Официальный сайт JUnit 5
  • Официальный сайт TestNG

Selenium для автотестов в браузерах

Когда упоминают Selenium, часто подразумевают ним инструмент для автоматизации UI тестов выполняемых в браузере. Однако Selenium это целое семейство продуктов:

  • Selenium WebDriver – библиотека для управления браузерами, основной продукт, разрабатываемый в рамках проекта.
  • Selenium Server – сервер для управления браузером с удалённой машины по сети.
  • Selenium Grid – ПО для объединения нескольких Selenium-серверов в кластер.
  • Selenium RC – устаревшая библиотека для управления браузерами.
  • Selenium IDE – плагин для Chrome и Firefoх для записи и последующего воспроизведения действий пользователя в браузере. В контексте автоматизации тестирования на Java полностью бесполезен. Ради интереса можно «потыкать», но не более.

В контексте автоматизации тестирования интерес представляет Selenium WebDriver и в некоторой степени Selenium Server и Grid, но последние два чаще заменяют альтернативными инструментами.

Для управления Selenium WebDriver из Java, используется библиотека selenium-java. Ниже приведен пример её подключения для Gradle.

implementation('org.seleniumhq.selenium:selenium-java') {
  version {
    strictly seleniumVersion
  }
}

Как это работает:

  • библиотека selenium-java позволяет обращаться из Java кода к Selenium WebDriver;
  • WebDriver должен быть скачан на машину, с которой будет происходить запуск тестов;
  • путь к WebDriver указывается в проекте с автотестами при инициализации драйвера в коде;
  • для каждого браузера и даже каждой версии браузера нужна соответствующая версия WebDriver. Логика выбора версии драйвера для тестов реализуется в коде самостоятельно или через сторонние библиотеки, например WebDriverManager (ссылка на Maven Repository);
  • на машине (локально или на сервере) на которой будут выполняться тесты должен быть установлен браузер той же версии, что и WebDriver.
  • инженер по автоматизации пишет автотесты используя команды selenium-java, а «под капотом» общение selenium-java и WebDriver осуществляются по REST-протоколу;
  • если тесты будут гоняться удалённо, потребуется Selenium Server.

Полезные ресурсы по Selenium:

  • Официальный сайт проекта Selenium
  • Онлайн учебники по Selenium Webdriver от kreisfahrer и COMAQA
  • Много полезного материала с конференции Selenium Camp
  • WebDriverManager (ссылка на Maven Repository) – библиотека упрощающая управление веб-драйвером (загрузка, настройка, обслуживание)
  • Курс Алексея Баранцева Selenium WebDriver: полное руководство
  • Полезный ролик на YouTube от Simple Automation по работе с Selenium Webdriver
  • Статья по Selenium от BrowserStack
  • Подготовка к собеседованию по Selenium – 30 вопросов

Selenide – прокачанный Selenium

Selenide – фреймворк, надстройка над Selenium WebDriver, но более простая и удобная в использовании.

Чтобы оценить всю мощь и прелесть Selenide, попробуйте написать десяток тестов на Selenium, а затем повторите тоже самое на Selenide.

Вот тут вместе с примерами собраны основные преимущества Selenide против Selenium, рекомендую ознакомиться, но если кратко:

  • инициализация браузера 1 строкой кода вместо 5;
  • не нужно выполнять закрытие браузера, Selenide сделает это самостоятельно;
  • простые конструкции для поиска элементов;
  • простые ассерты;
  • умные ожидания – если элемент не отобразился на странице, потому что еще не загрузился, Selenide подождёт 4 секунды (по-умолчанию);
  • поиск элемента по тексту;
  • создание скриншотов одной командой;
  • и много других «плюшек».

Полезные ресурсы по Selenide:

  • Быстрый старт по Selenide (как подключить к проекту и написать первый тест)
  • Selenide wiki
  • Как написать UI тест за 10 минут на Selenide
  • Эффективные UI-тесты на Selenide – статья с обзором возможностей Selenide от его создателя Андрея Солнцева
  • Примеры использования Selenide на GitHub
  • Подборка сниппетов демонстрирующих функционал Selenide

Selenoid – прокачанный Selenium Server

Если Selenide – это Selenium «на стероидах», то аналогичное можно сказать про Selenoid представляющегося лучшей альтернативой в отношении Selenium Server.

Selenium Server сложен в установке и поддержке. Все компоненты (Java, браузеры, бинарники WebDriver-ов, Selenium Server) необходимо устанавливать и конфигурировать вручную, что скорее всего вызовет затруднения если вы не продвинутый системный администратор или DevOps. Решения на Selenium Server часто не всегда стабильны. Зависшие браузеры, а часто и сервер приходится перезапускать.

В противовес Selenium Server установка Selenoid выполняется в несколько команд. Есть готовые образы для облачных серверов, в том числе для Yandex Cloud. Его отличает простой понятный интерфейс и простота в обслуживании. Зависшие браузеры автоматически перезапускаются. Имеется поддержка очередей и записи видео прохождения тестов.

Selenoid запускает браузеры изолированно в Docker-контейнерах, и это не дань моде, а полезная фича – если потребуется новый браузер, просто скачивается и подключается новый контейнер.

Если вы уже используете Selenium Server, но хотите перейти на Selenoid, кроме адреса сервера в существующем проекте ничего не придется менять.

Полезные ресурсы по Selenoid:

  • Официальный сайт Selenoid
  • Документация по Selenoid
  • Selenoid на GitHub

Так же рекомендую посмотреть доклад Ивана Крутого, одного из создателей Selenoid и видео с Heisenbug Павла Сенина.

Тестирование API: REST Assured и Retrofit

Для API автотестов не нужны ни Selenium, ни Selenide, ни Selenoid. Чтобы отправлять запросы и получать ответы используя REST понадобятся другие инструменты: REST Assured или Retrofit. Однако кроме API тестов они могут быть полезны и при тестировании UI, например если необходимо сконфигурировать сущность участвующую в тесте, тестируемый сервис и/или проверить результат теста, когда по API это сделать проще чем через UI.

Пример простого автотеста с использованием REST Assured.

Отчеты с Allure Report

Когда количество тестов перевалит за десяток, скорее всего понадобится анализировать результаты их выполнения. Консоль IntelliJ IDEA хоть и мощный инструмент, но все же не совсем для этого подходящий.

В TestNG функционал генерации отчетов работает «из коробки». JUnit не генерирует отчет, но сохраняет результат прогона автотестов, который можно привести к удобочитаемому с помощью плагинов. Однако есть инструмент, который превосходит по функционалу любое другое решение для построения отчётов – это Allure Report.

Функционал:

  • Группирует результаты веб и API-тестов, десктопных, мобильных в одном отчете.
  • Удобный интерфейс.
  • Тесты отображаются с подробным сценарием выполнения, включая. Если у теста есть вложения (логи, скриншоты, видео) Allure прилинкует их к тесту.
  • Гибкий фильтр, группировка, поиск.
  • Аналитика запуска тестов.
  • Поддержка не только Java, но и других языков программирования.
  • Интеграции с CI/CD системами.

Подробнее можно ознакомиться в докладе Артёма Ерошенко создателя Allure или почитать в статье на Хабре.

Полезные ресурсы по Allure Report:

  • Официальный сайт Allure Report
  • Как подключить к Java проекту
  • Документация Allure Report
  • Allure Report на GitHub

Continuous Integration

Настраивать CI прерогатива специалистов DevOps и тема для отдельной статьи. Однако, и автоматизатору данный скилл и понимание процессов несомненно полезны, особенно, если DevOps на проекте отсутствует.

Если не углубляться в подробности, то для тестирования важно уметь запускать автотесты при поставке новых фич в тестинг, релиз или продакшн и получать отчёт о результатах их прохождения. Указанное является лишь небольшой частью процесса непрерывной интеграции.

Самыми популярными CI/CD системами являются Jenkins, TeamCity, GitHub Actions, GitLab CI.

Полезные ресурсы по Jenkins:

  • Официальный сайт Jenkins
  • Мини руководство по Jenkins от Reg.ru
  • CI/CD на примере Jenkins. Автоматизация запуска тестов
  • Jenkins Pipeline. Что это и как использовать в тестировании
  • Jenkins 2. Приступаем к работе. Брент Ластер

Полезные ресурсы по TeamCity:

  • Официальный сайт TeamCity
  • Руководство по CI/CD в TeamCity
  • Пошаговые руководства TeamCity

Полезные ресурсы по GitHub Actions:

  • GitHub Actions
  • Автоматизируем все с Github Actions

Полезные ресурсы по GitLab CI:

  • GitLab CI/CD
  • GitLab CI для тестировщика (вебинар на YouTube)

Прочие полезные инструменты и библиотеки

Lombok – избавляет от необходимости написания шаблонного кода для геттеров, сеттеров, toString() и прочих, улучшая удобств и читаемость кода.

Gson – библиотека сериализации / десериализации для преобразования объектов Java в JSON и обратно.

Log4j – библиотека логирования и SLF4J – обёртка для различных библиотек логирования.

Сопутствующие технологии

Инженеру по автоматизированному тестированию недостаточно знаний одной лишь Java. В зависимости от тестируемого приложения или сервиса, придётся столкнуться со множеством других технологий.

Чтобы найти элемент на странице – нужно уметь строить локаторы, чтобы выполнить скрипт или поменять из кода значения в LocalStorage браузера – придется познакомиться с JavaScript, захотите обратиться к базе данных – пригодится SQL, понадобится определить действительно ли пользователь ввёл в поле адрес электронной почты добро пожаловать в мир регулярных выражений, а тестирование API подразумевает хорошее знание компьютерных сетей.

CSS и XPath локаторы

Автотесты для web-приложений постоянно взаимодействуют с web-элементами на странице. Нужно уметь строить их, используя локаторы.

Локатор (или селектор) – это выражение, которое идентифицирует элемент или группу элементов в DOM-дереве. Наиболее распространёнными являются CSS и XPath локаторы.

CSS локаторы включают в себя набор атрибутов web-элемента, в XPath – это путь до элемента в DOM-дереве.

Обычно на проекте используют один из видов локаторов, комбинировать их без понятной причины не рекомендуется. Выбор CSS или XPath зависит от личных предпочтений и договорённостей в команде.

  • Как писать CSS/XPath локаторы в Selenium WebDriver
  • Про типы локаторов и CSS, XPath, jQuery
  • Шпаргалка по локаторам
  • Мануал по XPath
  • И немного практических примеров в статье Эффективные UI-тесты на Selenide

HTML, CSS и JavaScript

  • HTML Academy: интерактивные онлай-курсы по HTML, CSS и JavaScript
  • HTMLBook.RU – онлайн самоучитель и справочник посвященный HTML и CSS
  • Онлайн курс по Веб-программированию от университета ИТМО
  • W3Schools – интерактивный учебник по web технологиям
  • Sololearn – интерактивный учебник по HTML, CSS, JS, JQuery, PHP, SQL, Java и другим языкам
  • Самый популярный онлайн учебник по JavaScript на русском языке
  • Справочник по JavaScript на Mozilla Developer Network
  • Учебник: Выразительный Javascript

Регулярные выражения

  • Регулярные выражения (Regexp) от Хекслет
  • Регулярные выражения. Джеффри Фридл
  • Регулярные выражения. Сборник рецептов. Ян Гойвертс, Стивен Левитан

Работа в консоли

  • Основы командной строки. Курс на Хекслет
  • Введение в Linux

Компьютерные сети

  • Онлайн курс Основы DevOps от Epam
  • Учебный курс Андрея Созыкина «Компьютерные сети» (на YouTube)
  • Компьютерные сети. Принципы, технологии, протоколы Виктор Олифер, Наталья Олифер

Для любителей курсов

  • Автоматизатор тестирования на Java от Яндекс Практикум
  • Школа инженеров по автоматизации тестирования QA.Guru
  • Инженер по тестированию: с нуля до middle от Нетологии
  • Тестировщик на Java
  • Тренинги Алексея Баранцева

Что еще

Научиться методу слепой печати

Советы новичкам:

  • Нажимайте клавиши только правильными пальцами и всегда возвращайте пальцы в исходную позицию «ФЫВА – ОЛДЖ», это основа метода слепого набора.
  • Не смотрите на клавиатуру.
  • Уделите внимание развитию безымянных пальцев и мизинцев обеих рук – их моторика хуже остальных, но они не меньше остальных пальцев участвуют в наборе текста.
  • На первых порах фокусируйтесь на качестве, а не на скорости, и постепенно доводите до автоматизма.

Сервисы для тренировки метода слепой печати:

  • Клавогонки
  • СОЛО на клавиатуре (только для WIndows)
  • Klava.org
  • Keybr

Подтянуть английский

  • Английский от Яндекс Практикума
  • Puzzle English
  • Puzzle Movies – английский по фильмам и сериалам
  • Duolingo
  • Lingualeo

Чек-лист автоматизатора

Прочтение этой статьи занимает 20 минут, но чтобы освоить приведенные в ней технологии, понадобится по меньшей мере год.

Если желание писать автотесты не угасло, надеюсь, что минимум – появилось понимание стека технологий для автоматизации тестирования, максимум – сложился некий «roadmap», из которого понятно, над чем стоит стоит подумать и какие скилы нужно подтянуть.

Чек-лист инженера по автоматизации тестирования на Java выглядит примерно так:

  • определился с языком программирования, в идеале – это язык, на котором пишут разработчики в команде, если это Java – есть понимание почему именно она;
  • может рассказать про ООП, его принципы (абстракция, инкапсуляция, наследование, полиморфизм) и объяснить что такое класс, интерфейс, объект;
  • знает чем различаются JRE, JVM и JDK;
  • знает, что такое переменные, каких типов они бывают, сколько места в памяти занимают и какие существуют модификаторы доступа;
  • умеет работать с условиями, циклами, массивами, коллекциями;
  • понимает, что такое PageObject, представляет, что такое паттерны и может применять некоторые из них;
  • чтобы запустить программу не использует мышь или тач-бар и знает ещё c десяток шоткатов;
  • может клонировать проект, отвести от него ветку, внести свои изменения, сделать коммит, запушить обратно в общий репозиторий и не боится конфликтов и ребейзов;
  • не путается в названиях Gradle, Maven, JUnit, TestNG, понимает их назначение и может использовать в проекте;
  • знает что такое Selenium, Selenide, Selenoid и использует две из трёх технологий;
  • без шпаргалок составляет CSS и XPath локаторы;
  • умеет использовать REST Assured или Retrofit для API-тестов;
  • любит или не любит Lombok;
  • каждый день заглядывает в Allure Report;
  • уже настроил несколько пайплайнов в Jenkins или поигрался Selenoid в GitHub Actions;
  • … большой молодец раз осилил так много технологий.

На этом всё. Но вы можете поддержать проект. Даже небольшая сумма поможет нам писать больше полезных статей.

Если статья помогла или понравилась, пожалуйста поделитесь ей в соцсетях.

Содержание

  1. Что такое автотесты
  2. Документация
  3. Инструменты
  4. Паттерны проектирования
  5. Что можно автоматизировать
  6. Советы для разработки автотестов
  7. Общий код стоит выносить
  8. Писать переиспользуемый код
  9. Тесты должны быть удобными
  10. Тесты должны быть простыми
  11. Разделение на модули
  12. Интеграции
  13. Главное кратко

Когда проект становится очень большим, а ручные тесты отнимают все больше времени и средств, требуется автоматизация тестирования. Тестировщик Даниил Шатухин рассказывает, как выстроить архитектуру автотестов на Java, чтобы потом не пришлось все срочно переделывать и оптимизировать.

Что такое автотесты

Под автоматизацией тестирования понимают написание скриптов, которые выполняют тесты за мануальных тестировщиков. Такие системы состоят из сложных сценариев проверки функциональности проектов, сбора статистики, фиксирования багов и генерации отчетности. Может показаться, что если однажды автоматизировать базу тестов, то можно навсегда забыть про долгий процесс тестирования каждого билда. Но автотесты надо постоянно актуализировать и поддерживать. Это первое, о чем стоит задуматься до внедрения автотестов в проект.

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

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

Документация

Подумайте, что именно предстоит автоматизировать.

Составьте тест-план. Он поможет понять, что нужно тестировать и какие состояния можно считать успешным завершением тестов. В тест-плане кратко описывают тестируемый продукт, платформы и операционные системы, на которых предстоит работать. Здесь указывают критерии завершения тестов.

Подготовьте тест-кейсы. Это подробное текстовое описание прохождения каждого тестового сценария. Такой подготовительный этап можно назвать самым ответственным. Необходимо не просто собрать коллекцию тест-кейсов и начать писать код — надо понять, какие части проекта нужно автоматизировать в первую очередь. Обычно автотесты начинают писать, чтобы сократить время, которое уходит на ручное тестирование. Поэтому в приоритете:

  • рутинные тесты, которые занимают много времени, часто запускаются и требуют постоянного воспроизведения. Например, в проекте есть анкета для обратной связи с большим количеством полей и входных данных. Ручное заполнение может занимать 5–10 минут, а запуск автоматизированного теста — несколько секунд. Автоматизация позволит освободить время на более приоритетные и интересные задачи;
  • места с заведомо большим количеством багов. На каждом проекте они разные, но к ним, например, может относиться и часто обновляемый код.

Тест-кейсы следует описывать максимально детально и подробно; обязательно указывать состояние, которое можно считать успешным для завершения теста. Некоторые действия сложно автоматизировать. Например, с помощью скрипта можно проверить наличие картинки на сайте, но не ее содержимое. В этом случае задачу проще оставить для ручного тестирования.

Инструменты

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

При выборе фреймворка стоит обращать внимание на наличие подробной документации, его популярность и актуальность. Если последний раз фреймворк обновляли несколько лет назад, то его выбирать не стоит. Также необходимо хранить историю версий кода автотестов, генерировать подробные отчеты и выполнять интеграцию CI/CD.

Обычно стек инструментов и технологий для автоматизации на Java выглядит так:

  • Selenide — популярный фреймворк для автоматизации тестирования веба на базе Selenium WebDriver;
  • Allure Testops — инструмент для простого создания подробных отчетов. Поддерживает скриншоты, скринкасты и снапшоты состояния страниц во время выполнения теста. Все это позволяет не только увидеть наличие ошибок, но и посмотреть на сами ошибки визуально;

Отчеты в Allure Testops

Интерфейс запущенных тестов в Allure Testops

  • JUnit — инструмент для модульного тестирования ПО на Java;
  • Rest Assured — библиотека для работы с REST-службами и тестирования API;
  • Jenkins — открытая система для непрерывной интеграции ПО;

Непрерывная интеграция Jenkins

Пример запущенных и отработанных тестов в Jenkins

  • Git — распределенная система управления версиями. Можно использовать любой удобный сервис, к примеру GitHub, GitLab или Bitbucket. При желании можно поднять собственный git-сервер.

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

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

Паттерны проектирования

Автоматизация тестирования — уже сложившаяся сфера со своими правилами и подходами. Для упрощения разработки существует набор паттернов проектирования:

  • Для структурирования кода существует понятие Page Object. Принцип заключается в объединении элементов страниц в свойства класса. Важно, что для каждой страницы создается ровно один класс, который содержит элементы в качестве свойств. В одном модуле мы храним локаторы, а в другом — взаимодействуем с ними. Это помогает повторно использовать локаторы и давать им понятные названия.
  • Для запуска одних и тех же тестов с разными данными обычно используется подход Data Providers. Буквально представьте, что в вашем проекте есть отдельный модуль, поставляющий данные для тестов. Вам не надо самостоятельно генерировать данные, а достаточно просто вызвать ранее написанный модуль. Это упростит работу и поможет сэкономить время, ведь можно будет просто обратиться к «поставщику».
  • Также следует использовать декораторы и дополнительные методы фреймворков, к которым можно отнести аннотации JUnit. Например, с помощью аннотации Issue, Story, CsvSource и Feature можно указать версию тестируемого приложения, кратко описать тестовый сценарии, добавить ссылку на тест в трекинговую систему или указать список тестовых данных.

Что можно автоматизировать

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

Мобильные приложения и «железо» обычно тестируют отдельные QA-команды. Связано это с тем, что в тестировании приложений есть свои особенности и сценарии, которые практически не встречаются в веб-приложениях, а для тестирования «железа» необходимы специальные навыки. Фронтенд- и бэкенд-тестировщики обычно работают вместе и часто общаются с разработчиками этих систем.

Из всех тест-кейсов надо выбрать наиболее приоритетные. Если проект находится на стадии разработки, то надо начинать с тестирования бэкенда. Дело в том, что клиентская часть еще может поменяться, и тогда QA-команде придется переписывать тесты. А вот серверную часть вряд ли переделают перед самым запуском. Но и это не все, эти тестовые сценарии тоже надо рассортировать по приоритету.

Цель компании — получать прибыль; добиться ее можно с помощью веб-приложения. Поэтому в первую очередь следует покрывать тестами те части проекта, которые отвечают за продажи и аналитику. К примеру, на сайте есть форма оплаты и обратной связи. В первую очередь стоит обратить внимание на тестирование части, которая отвечает за получение денег. Ведь если никто не сможет купить продукт, то и обратная связь не понадобится.

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

Советы для разработки автотестов

Советы ниже помогут с самого начала выстроить грамотную архитектуру и работу в QA-команде. Также работодатели чаще обращают внимание на соискателей, которые уже переняли лучшие практики индустрии и умеют ими пользоваться.

Общий код стоит выносить

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

Писать переиспользуемый код

Надо стараться писать универсальные методы и конструкции, которые можно будет использовать повторно. Это экономит время на разработке и ускоряет процесс автоматизации. Куда быстрее дополнить уже готовый метод, чем писать его с нуля.

Тесты должны быть удобными

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

Тесты должны быть простыми

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

Разделение на модули

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

Интеграции

Над автоматизацией тестирования обычно работает целая команда QA-отдела. И код надо писать таким образом, чтобы его можно было использовать внутри проекта. К примеру, разработчику необходимо протестировать систему, которая требует создания нового пользователя при каждой проверке. В этом случае можно самому написать модуль регистрации и потратить время, а можно обратить внимание, что коллеги уже успели это сделать, и использовать их модуль. Если каждый член команды будет думать о переиспользовании его кода внутри отдела, то работа будет идти быстрее.

Главное кратко

  • Автоматизация тестирования — сложный процесс, требующий времени на внедрение и ресурсов на поддержание. Нельзя написать код один раз и оставить его без присмотра.
  • Автотесты принесут пользу только при грамотном подходе и выборе инструментов. Иначе они просто заберут силы и время.
  • Не надо автоматизировать всё подряд. Важно в первую очередь заняться теми частями проекта, которые имеют наибольшую значимость.
  • Тесты должны быть «человечными». Зеленая галочка в терминале после прогона не даст никакой полезной информации менеджерам и другим участникам команды. Поэтому следует уделить время генерации подробной и понятной отчетности, из которой каждый сможет получить необходимые для себя данные.
  • Код автотестов должен быть простым и понятным. Сложные конструкции и низкоуровневые вставки сделают только хуже.
  • Использование большого количества сторонних библиотек чаще несет больше вреда, чем пользы. Библиотеки тянут за собой зависимости, которые замедляют сборку. Некоторые вещи уже могут быть реализованы в стандартной библиотеке Java.

Пишем автотест с использованием Selenium Webdriver, Java 8 и паттерна Page Object

В этой статье рассматривается создание достаточного простого автотеста. Статья будет полезна начинающим автоматизаторам.

Материал изложен максимально доступно, однако, будет значительно проще понять о чем здесь идет речь, если Вы будете иметь хотя бы минимальные представления о языке Java: классы, методы, etc.

  • установленная среда разработки Intellij IDEA (является самой популярной IDE, для большинства случаев достаточно бесплатной версии Community Edition);
  • установленные Java (jdk/openjdk) и Maven, прописанные в системные окружения ОС;
  • браузер Chrome и chromedriver — программа для передачи команд браузеру.

Создание проекта

Запустим Intellij IDEA, пройдем первые несколько пунктов, касающихся отправки статистики, импорта проектов, выбора цветовой схемы и т.д. — просто выберем параметры по умолчанию.

В появившемся в конце окне выберем пункт «Create New Project», а в нем тип проекта Maven. Окно будет иметь вид:

image

  • Maven — это инструмент сборки Java проектов;
  • Project SDK — версия Java, которая установлена на компьютере;
  • Create from archetype — это возможность создавать проект с определенным архетипом (на данном этапе данный чекбокс отмечать не нужно).

Нажмем «Next». Откроется следующее окно:

image

Groupid и Artifactid — идентификаторы проекта в Maven. Существуют определенные правила заполнения этих пунктов:

  • Groupid — название организации или подразделения занимающихся разработкой проекта. В этом пункте действует тоже правило как и в именовании пакетов Java: доменное имя организации записанное задом наперед. Если у Вас нет своего доменного имени, то можно использовать свой э-мейл, например com.email.email;
  • Artifactid — название проекта;
  • Version — версия проекта.

Нажмем «Finish»: IDE автоматически откроет файл pom.xml:

image

В нем уже появилась информация о проекте, внесенная на предыдущем шаге: Groupid, Artefiactid, Version. Pom.xml — это файл который описывает проект. Pom-файл хранит список всех библиотек (зависимостей), которые используются в проекте.

Для этого автотеста необходимо добавить две библиотеки: Selenium Java и Junit. Перейдем на центральный репозиторий Maven mvnrepository.com, вобьем в строку поиска Selenium Java и зайдем в раздел библиотеки:

image

Выберем нужную версию (в примере будет использована версия 3.14.0). Откроется страница:

image

Копируем содержимое блока «Maven» и вставим в файл pom.xml в блок

Таким образом библиотека будет включена в проект и ее можно будет использовать. Аналогично сделаем с библиотекой Junit (будем использовать версию 4.12).

image

Создание пакета и класса

Раскроем структуру проекта. Директория src содержит в себе две директории: «main» и «test». Для тестов используется, соответственно, директория «test». Откроем директорию «test», кликом правой клавиши мыши по директории «java» выберем пункт «New», а затем пункт «Package». В открывшемся диалоговом окне необходимо ввести название пакета. Имя базового пакета должно носить тоже имя, что и Groupid — «org.example».

Следующий шаг — создание класса Java, в котором пишется код автотеста. Кликом правой клавиши мыши по названию пакета выберем пункт «New», а затем пункт «Java Class».

В открывшемся диалоговом окне необходимо ввести имя Java класса, например, LoginTest (название класса в Java всегда должно начинаться с большой буквы). В IDE откроется окно тестового класса:

image

Настройка IDE

Прежде чем начать, необходимо настроить IDE. Кликом правой клавиши мыши по названию проекта выберем пункт «Open Module Settings». В открывшемся окне во вкладке «Sources» поле «Language level» по умолчанию имеет значение 5. Необходимо изменить значение поля на 8 (для использования всех возможностей, присутствующих в этой версии Java) и сохранить изменения:

image

Далее необходимо изменить версию компилятора Java: нажмем меню «File», а затем выберем пункт Settings.

В открывшемся перейдем «Build, Execution, Deployment» -> «Compiler» -> «Java Compiler». По умолчанию установлена версия 1.5. Изменим версию на 8 и сохраним изменения:

image

Test Suite

  1. Пользователь открывает страницу аутентификации;
  2. Пользователь производит ввод валидных логина и пароля;
  3. Пользователь удостоверяется в успешной аутентификации — об этом свидетельствует имя пользователя в верхнем правом углу окна;
  4. Пользователь осуществляет выход из аккаунта путем нажатия на имя пользователя в верхнем правом углу окна с последующим нажатием на кнопку «Выйти…».

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

Для примера будет использоваться аккаунт Яндекс (учетная запись заранее создана вручную).

Первый метод

В классе LoginTest будет описана логика теста. Создадим в этом классе метод «setup()», в котором будут описаны предварительные настройки. Итак, для запуска браузера необходимо создать объект драйвера:

Перед созданием объекта WebDriver следует установить зависимость, определяющую путь к chomedriver (в ОС семейства Windows дополнительно необходимо указывать расширение .exe):

Чтобы ход теста отображался в полностью открытом окне, необходимо сказать об этом драйверу:

Случается, что элементы на страницах доступны не сразу, и необходимо дождаться появления элемента. Для этого существуют ожидания. Они бывают двух видов: явные и неявные. В примере будет использовано неявное ожидание Implicitly Wait, которое задается вначале теста и будет работать при каждом вызове метода поиска элемента:

Таким образом, если элемент не найден, то драйвер будет ждать его появления в течении заданного времени (10 секунд) и шагом в 500 мс. Как только элемент будет найден, драйвер продолжит работу, однако, в противном случае тест упадем по истечению времени.

Для передачи драйверу адреса страницы используется команда:

Выносим настройки

Для удобства вынесем название страницы в отдельный файл (а чуть позже и некоторые другие параметры).

Создадим в каталоге «test» еще один каталог с названием «resources», а в нем обычный файл «conf.properties», в который поместим переменную:

а также внесем сюда путь до драйвера

image

В пакете «org.example» создадим еще один класс «ConfProperties», который будет читать записанные в файл «conf.properties» значения:

image

Обзор первого метода

image

Метод «setup()» пометим аннотацией Junit «@BeforeClass», которая указывает на то, что метод будет выполняться один раз до выполнения всех тестов в классе. Тестовые методы в Junit помечаются аннотацией Test.

Page Object

При использовании Page Object элементы страниц, а также методы непосредственного взаимодействия с ними, выносятся в отдельный класс.

Создадим в пакете «org.example» класс LoginPage, который будет содержать локацию элементов страницы логина и методы для взаимодействия с этими элементами.

Откроем страницу авторизации в сервисах Яндекс (https://passport.yandex.ru/auth) в браузере Chrome. Для определения локаторов элементов страницы, с которыми будет взаимодействовать автотест, воспользуемся инструментами разработчика. Кликом правой кнопки мыши вызовем меню «Просмотреть код». В появившейся панели нажмем на значок курсора (левый верхний угол панели разработчика) и наведем курсор на интересующий нас элемент — поле ввода логина.

В результате мы увидим этот элемент среди множества других. Теперь мы можем скопировать его локацию. Для этого кликаем правой кнопкой мыши по выделенному в панели разработчика элементу, выбираем меню «Copy» -> «Copy XPath».

Для локации элементов в Page Object используется аннотация @FindBy.

Напишем следующий код:

Таким образом мы нашли элемент на страницу и назвали его loginField (элемент доступен только внутри класса LoginPage, т.к. является приватным).

Однако, такой длинный и страшный xpath использовать не рекомендуется (рекомендую к прочтению статью «Не так страшен xpath как его незнание». Если присмотреться, то можно увидеть, что поле ввода логина имеет уникальный id:

image

Воспользуемся этим и изменим поиск элемента по xpath:

Теперь вероятность того, что поле ввода пароля будет определено верно даже в случае изменения местоположения элемента на странице, возросла.

Аналогично изучим следующие элементы и получим их локаторы.

Поле ввода пароля:

А теперь напишем методы для взаимодействия с элементами.

Метод ввода логина:

Метод ввода пароля:

Метод нажатия кнопки входа:

Для того, чтобы аннотация @FindBy заработала, необходимо использовать класс PageFactory. Для этого создадим конструктор и передадим ему в качестве параметра объект Webdriver:

image

После авторизации мы попадаем на страницу пользователя. Т.к. это уже другая страница, в соответствии с идеологией Page Object нам понадобится отдельный класс для ее описания. Создадим класс ProfilePage, в котором определим локаторы для имени пользователя (как показателя успешного входа в учетную запись), а также кнопки выхода из аккаунта. Помимо этого, напишем методы, которые будут получать имя пользователя и нажимать на кнопку выхода.

Итого, страница будет иметь следующий вид:

image

Интересный момент: в метод getUserName() пришлось добавить еще одно ожидание, т.к. страница «тяжелая» и загружалась довольно медленно. В итоге тест падал, потому что метод не мог получить имя пользователя. Метод getUserName() с ожиданием:

Вернемся к классу LoginTest и добавим в него созданные ранее классы-страницы путем объявления статических переменных с соответствующими именами:

Сюда же вынесем переменную для драйвера

В аннотации @BeforeClass создаем экземпляры классов созданных ранее страниц и присвоим ссылки на них. Создание экземпляра происходит с помощью оператора new. В качестве параметра указываем созданный перед этим объект driver, который передается конструкторам класса, созданным ранее:

А создание экземпляра драйвера приведем к следующему виду (т.к. он объявлен в качестве переменной):

Теперь можно перейти непосредственно к написанию логики теста. Создадим метод loginTest() и пометим его соответствующей аннотацией:

Осталось лишь корректно все завершить. Создадим финальный метод и пометим его аннотацией @AfterClass (методы помеченные этой аннотацией выполняются один раз, после завершения всех тестовых методов класса).

В этом методе осуществляется вход в меню пользователя и нажатие кнопки «Выйти», чтобы разлогиниться.

Последняя строка нужна для закрытия окна браузера.

Обзор теста

Запуск автотеста

Для запуска автотестов в Intellij Idea имеется несколько способов:

  • Alt+Shift+F10;
  • Клик правой клавишей мышки по имени тестового класса, после чего в открывшемся меню выбрать Run;

В результате выполнения автотеста, в консоли Idea я вижу, что тестовый метод loginTest() пройден успешно:

22 практических совета по тестированию автоматизации с Selenium WebDriver

Автоматизация тестирования с помощью Selenium позволила тестировщикам веб-сайтов по всему миру легко выполнять автоматическое тестирование веб-сайтов. Webdriver является ключевым компонентом платформы Selenium, с помощью которого вы можете выполнять автоматическое перекрестное браузерное тестирование вашего веб-сайта или веб-приложения на различных типах браузеров, например, Google Chrome, Mozilla Firefox, Safari, Opera, Internet Explorer, Microsoft Edge и т. Д.

Основным преимуществом выполнения автоматизации тестирования с Selenium Webdriver перед другими инструментами / средами веб-автоматизации является поддержка широкого ряда языков программирования, а именно Python, Java, C #, Ruby, PHP, JavaScript, .Net, Perl и т. Д. Если вы Если вы новичок в автоматизации тестирования с Selenium WebDriver, то вы можете взглянуть на наш учебник Selenium WebDriver по автоматическому межбраузерному тестированию, где мы поговорим об общей архитектуре Selenium и о том, как можно использовать эту платформу с популярными языками программирования. Вы также можете проверить мою предыдущую статью об учебнике по настройке Selenium Grid для кросс-браузерного тестирования , чтобы использовать возможности параллельного тестирования с Selenium . Независимо от используемого языка программирования, существуют определенные рекомендации, применимые для автоматизации тестирования с помощью Selenium Webdriver (независимо от языка разработки).

В этой статье я поделюсь с вами некоторыми ключевыми советами по автоматизации тестирования Selenium, которые касаются аспектов оптимизации кода, повышения производительности, динамической загрузки веб-страниц, обработки кода CSS и HTML и т. Д.

Примечание. Большинство этих советов по кодированию для автоматизации тестирования с Selenium WebDriver носят общий характер и могут применяться независимо от языка программирования, используемого для разработки тестовых сценариев. Однако для демонстрации ниже мы использовали Selenium с языком Python.

Selenium Совет № 1 – Установка исполняемого пути веб-драйвера Selenium

Для связи с тестируемым браузером вам необходимо сначала загрузить соответствующий плагин / веб-драйвер с их официального сайта . Этот плагин будет отвечать за связь с браузером, и он должен присутствовать на вашем компьютере (на котором вы разрабатываете тесты). Путь к плагину / веб-драйверу должен быть задан в конфигурации Selenium Webdriver.

Хотя плагин / веб-драйвер можно разместить в любом месте, поскольку вы можете указать статический / относительный путь в конфигурации Selenium Webdriver, этот подход может быть подвержен ошибкам, и вам необходимо отслеживать путь к файлу. Лучшим и более надежным подходом является размещение соответствующего Selenium Webdriver в месте, где присутствует исполняемый файл драйвера, и в этом случае вам не нужно указывать путь к исполняемому файлу в конфигурации Selenium Webdriver.

Пишем автотест с использованием Selenium Webdriver, Java 8 и паттерна Page Object

В этой статье рассматривается создание достаточного простого автотеста. Статья будет полезна начинающим автоматизаторам.

Материал изложен максимально доступно, однако, будет значительно проще понять о чем здесь идет речь, если Вы будете иметь хотя бы минимальные представления о языке Java: классы, методы, etc.

  • установленная среда разработки Intellij IDEA (является самой популярной IDE, для большинства случаев достаточно бесплатной версии Community Edition);
  • установленные Java (jdk/openjdk) и Maven, прописанные в системные окружения ОС;
  • браузер Chrome и chromedriver — программа для передачи команд браузеру.

Создание проекта

Запустим Intellij IDEA, пройдем первые несколько пунктов, касающихся отправки статистики, импорта проектов, выбора цветовой схемы и т.д. — просто выберем параметры по умолчанию.

В появившемся в конце окне выберем пункт «Create New Project», а в нем тип проекта Maven. Окно будет иметь вид:

image

  • Maven — это инструмент сборки Java проектов;
  • Project SDK — версия Java, которая установлена на компьютере;
  • Create from archetype — это возможность создавать проект с определенным архетипом (на данном этапе данный чекбокс отмечать не нужно).

Нажмем «Next». Откроется следующее окно:

image

Groupid и Artifactid — идентификаторы проекта в Maven. Существуют определенные правила заполнения этих пунктов:

  • Groupid — название организации или подразделения занимающихся разработкой проекта. В этом пункте действует тоже правило как и в именовании пакетов Java: доменное имя организации записанное задом наперед. Если у Вас нет своего доменного имени, то можно использовать свой э-мейл, например com.email.email;
  • Artifactid — название проекта;
  • Version — версия проекта.

Нажмем «Finish»: IDE автоматически откроет файл pom.xml:

image

В нем уже появилась информация о проекте, внесенная на предыдущем шаге: Groupid, Artefiactid, Version. Pom.xml — это файл который описывает проект. Pom-файл хранит список всех библиотек (зависимостей), которые используются в проекте.

Для этого автотеста необходимо добавить две библиотеки: Selenium Java и Junit. Перейдем на центральный репозиторий Maven mvnrepository.com, вобьем в строку поиска Selenium Java и зайдем в раздел библиотеки:

image

Выберем нужную версию (в примере будет использована версия 3.14.0). Откроется страница:

image

Копируем содержимое блока «Maven» и вставим в файл pom.xml в блок

Таким образом библиотека будет включена в проект и ее можно будет использовать. Аналогично сделаем с библиотекой Junit (будем использовать версию 4.12).

image

Создание пакета и класса

Раскроем структуру проекта. Директория src содержит в себе две директории: «main» и «test». Для тестов используется, соответственно, директория «test». Откроем директорию «test», кликом правой клавиши мыши по директории «java» выберем пункт «New», а затем пункт «Package». В открывшемся диалоговом окне необходимо ввести название пакета. Имя базового пакета должно носить тоже имя, что и Groupid — «org.example».

Следующий шаг — создание класса Java, в котором пишется код автотеста. Кликом правой клавиши мыши по названию пакета выберем пункт «New», а затем пункт «Java Class».

В открывшемся диалоговом окне необходимо ввести имя Java класса, например, LoginTest (название класса в Java всегда должно начинаться с большой буквы). В IDE откроется окно тестового класса:

image

Настройка IDE

Прежде чем начать, необходимо настроить IDE. Кликом правой клавиши мыши по названию проекта выберем пункт «Open Module Settings». В открывшемся окне во вкладке «Sources» поле «Language level» по умолчанию имеет значение 5. Необходимо изменить значение поля на 8 (для использования всех возможностей, присутствующих в этой версии Java) и сохранить изменения:

image

Далее необходимо изменить версию компилятора Java: нажмем меню «File», а затем выберем пункт Settings.

В открывшемся перейдем «Build, Execution, Deployment» -> «Compiler» -> «Java Compiler». По умолчанию установлена версия 1.5. Изменим версию на 8 и сохраним изменения:

image

Test Suite

  1. Пользователь открывает страницу аутентификации;
  2. Пользователь производит ввод валидных логина и пароля;
  3. Пользователь удостоверяется в успешной аутентификации — об этом свидетельствует имя пользователя в верхнем правом углу окна;
  4. Пользователь осуществляет выход из аккаунта путем нажатия на имя пользователя в верхнем правом углу окна с последующим нажатием на кнопку «Выйти…».

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

Для примера будет использоваться аккаунт Яндекс (учетная запись заранее создана вручную).

Первый метод

В классе LoginTest будет описана логика теста. Создадим в этом классе метод «setup()», в котором будут описаны предварительные настройки. Итак, для запуска браузера необходимо создать объект драйвера:

Перед созданием объекта WebDriver следует установить зависимость, определяющую путь к chomedriver (в ОС семейства Windows дополнительно необходимо указывать расширение .exe):

Чтобы ход теста отображался в полностью открытом окне, необходимо сказать об этом драйверу:

Случается, что элементы на страницах доступны не сразу, и необходимо дождаться появления элемента. Для этого существуют ожидания. Они бывают двух видов: явные и неявные. В примере будет использовано неявное ожидание Implicitly Wait, которое задается вначале теста и будет работать при каждом вызове метода поиска элемента:

Таким образом, если элемент не найден, то драйвер будет ждать его появления в течении заданного времени (10 секунд) и шагом в 500 мс. Как только элемент будет найден, драйвер продолжит работу, однако, в противном случае тест упадем по истечению времени.

Для передачи драйверу адреса страницы используется команда:

Выносим настройки

Для удобства вынесем название страницы в отдельный файл (а чуть позже и некоторые другие параметры).

Создадим в каталоге «test» еще один каталог с названием «resources», а в нем обычный файл «conf.properties», в который поместим переменную:

а также внесем сюда путь до драйвера

image

В пакете «org.example» создадим еще один класс «ConfProperties», который будет читать записанные в файл «conf.properties» значения:

image

Обзор первого метода

image

Метод «setup()» пометим аннотацией Junit «@BeforeClass», которая указывает на то, что метод будет выполняться один раз до выполнения всех тестов в классе. Тестовые методы в Junit помечаются аннотацией Test.

Page Object

При использовании Page Object элементы страниц, а также методы непосредственного взаимодействия с ними, выносятся в отдельный класс.

Создадим в пакете «org.example» класс LoginPage, который будет содержать локацию элементов страницы логина и методы для взаимодействия с этими элементами.

Откроем страницу авторизации в сервисах Яндекс (https://passport.yandex.ru/auth) в браузере Chrome. Для определения локаторов элементов страницы, с которыми будет взаимодействовать автотест, воспользуемся инструментами разработчика. Кликом правой кнопки мыши вызовем меню «Просмотреть код». В появившейся панели нажмем на значок курсора (левый верхний угол панели разработчика) и наведем курсор на интересующий нас элемент — поле ввода логина.

В результате мы увидим этот элемент среди множества других. Теперь мы можем скопировать его локацию. Для этого кликаем правой кнопкой мыши по выделенному в панели разработчика элементу, выбираем меню «Copy» -> «Copy XPath».

Для локации элементов в Page Object используется аннотация @FindBy.

Напишем следующий код:

Таким образом мы нашли элемент на страницу и назвали его loginField (элемент доступен только внутри класса LoginPage, т.к. является приватным).

Однако, такой длинный и страшный xpath использовать не рекомендуется (рекомендую к прочтению статью «Не так страшен xpath как его незнание». Если присмотреться, то можно увидеть, что поле ввода логина имеет уникальный id:

image

Воспользуемся этим и изменим поиск элемента по xpath:

Теперь вероятность того, что поле ввода пароля будет определено верно даже в случае изменения местоположения элемента на странице, возросла.

Аналогично изучим следующие элементы и получим их локаторы.

Поле ввода пароля:

А теперь напишем методы для взаимодействия с элементами.

Метод ввода логина:

Метод ввода пароля:

Метод нажатия кнопки входа:

Для того, чтобы аннотация @FindBy заработала, необходимо использовать класс PageFactory. Для этого создадим конструктор и передадим ему в качестве параметра объект Webdriver:

image

После авторизации мы попадаем на страницу пользователя. Т.к. это уже другая страница, в соответствии с идеологией Page Object нам понадобится отдельный класс для ее описания. Создадим класс ProfilePage, в котором определим локаторы для имени пользователя (как показателя успешного входа в учетную запись), а также кнопки выхода из аккаунта. Помимо этого, напишем методы, которые будут получать имя пользователя и нажимать на кнопку выхода.

Итого, страница ввода логина будет иметь следующий вид:

image

Интересный момент: в метод getUserName() пришлось добавить еще одно ожидание, т.к. страница «тяжелая» и загружалась довольно медленно. В итоге тест падал, потому что метод не мог получить имя пользователя. Метод getUserName() с ожиданием:

Вернемся к классу LoginTest и добавим в него созданные ранее классы-страницы путем объявления статических переменных с соответствующими именами:

Сюда же вынесем переменную для драйвера

В аннотации @BeforeClass создаем экземпляры классов созданных ранее страниц и присвоим ссылки на них. Создание экземпляра происходит с помощью оператора new. В качестве параметра указываем созданный перед этим объект driver, который передается конструкторам класса, созданным ранее:

А создание экземпляра драйвера приведем к следующему виду (т.к. он объявлен в качестве переменной):

Теперь можно перейти непосредственно к написанию логики теста. Создадим метод loginTest() и пометим его соответствующей аннотацией:

Осталось лишь корректно все завершить. Создадим финальный метод и пометим его аннотацией @AfterClass (методы помеченные этой аннотацией выполняются один раз, после завершения всех тестовых методов класса).

В этом методе осуществляется вход в меню пользователя и нажатие кнопки «Выйти», чтобы разлогиниться.

Последняя строка нужна для закрытия окна браузера.

Обзор теста

Запуск автотеста

Для запуска автотестов в Intellij Idea имеется несколько способов:

  • Alt+Shift+F10;
  • Клик правой клавишей мышки по имени тестового класса, после чего в открывшемся меню выбрать Run;

В результате выполнения автотеста, в консоли Idea я вижу, что тестовый метод loginTest() пройден успешно:

Selenium — это инструмент с открытым кодом для автоматизации тестирования WEB. С его помощью можно заменить рутинные операции, которые вынуждены делать мануальные тестировщики. Например, текстовый ввод или однотипные взаимодействия со множеством элементов страниц. Также Selenium облегчает тестирование разных локализаций, потому что взаимодействие с элементами страницы происходит на уровне кода.

Плюс Selenium в том, что он поддерживает самые популярные языки программирования (Java, Python, JavaScript, PHP).

Чтобы лучше понять, как работает Selenium, напишем тест на Java.

Сравнение имени пользователя и логина: пишем код

Напишем тест, который будет открывать «Википедию», логиниться и проверять, соответствует ли имя пользователя его логину.

  • 1. Устанавливаем WebDriver— драйвер, который управляет работой браузера (открывает страницы и отправляет им команды). Тест будет написан для Chrome, поэтому понадобится драйвер для последней версии Chrome.
  • 2. Подтягиваем зависимость для Selenium-java в pom.xml Maven-проекта.
<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-java</artifactId>
  <version>4.0.0</version>
</dependency>
  • 3. Создаем три класса в папке Test:
    • WikiLoginPage (отвечает за работу со страницей авторизации).
    • WikiMainPage (отвечает за страницу, которая загружается после авторизации).
    • WikiLoginTest (основной тестовый класс).

    Отдельные классы для разных страниц создаем с помощью паттерна Page Object. Это паттерн автоматизации, который моделирует страницы и их элементы как отдельные сущности и свойства.

  • 4. Реализовываем класс WikiLoginTest. С помощью метода openWikiLoginPage создаем экземпляры драйвера и классов страниц (wikiLoginPage, wikiMainPage).

Также необходимо выставить небольшую задержку в 5 секунд, чтобы все статические элементы страницы успели загрузиться — timeouts().implicitlyWait(Duration.ofSeconds(5)). Аннотация @BeforeClass говорит о том, что этот метод будет вызван только один раз до запуска всех тестов. Метод quitDriver завершает работу драйвера и закрывает браузер.

Аннотация @AfterClass обеспечивает его вызов только после того, как отработают все остальные методы. В переменные name и password прописываем данные пользователя, которые будем проверять.

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import java.time.Duration;

public class WikiLoginTest {
    public static WebDriver driver;
    public static WikiLoginPage wikiLoginPage;
    public static WikiMainPage wikiMainPage;
    public static String url = "https://ru.wikipedia.org/w/index.php?title=Служебная:Вход&returnto=Заглавная+страница";
    public static String name = "your_name";
    public static String password = "your_password";

    @BeforeClass
    public static void openWikiLoginPage() {
        System.setProperty("webdriver.chrome.driver", "c:/chromedriver.exe");
        driver = new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
        driver.get(url);

        wikiLoginPage = new WikiLoginPage(driver);
        wikiMainPage = new WikiMainPage(driver);
    }

    @AfterClass
    public static void quitDriver() {
        driver.quit();
    }
}
  • 5. Теперь нужен класс для работы со страницей ввода имени пользователя и пароля — WikiLoginPage. В нем с помощью PageFactory создаем хранилища объектов. К статическим объектам страницы (WebElement) обращаемся с помощью локаторов и аннотации @FindBy. В @FindBy передаем id элемента. Чтобы выбрать идентификатор для элемента, в Google DevTools нажимаем правой кнопкой мыши на элемент, а затем выбираем «посмотреть код» и копируем id.

  • В тесте мы будем использовать три локатора:
    • nameField — для имени пользователя;
    • passwordField — для пароля;
    • loginButton — для кнопки авторизации.

    Методы inputName и inputPassword эмулируют ввод имени и пароля, а метод ClickLoginButton — нажатие кнопки авторизации.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class WikiLoginPage {
    public WebDriver driver;

    public WikiLoginPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
        this.driver = driver;
    }

    @FindBy(id = "wpName1")
    WebElement nameField;

    @FindBy(id = "wpPassword1")
    WebElement passwordField;

    @FindBy(id = "wpLoginAttempt")
    WebElement loginButton;

    public void inputName(String name) {
        nameField.sendKeys(name);
    }

    public void inputPassword(String password) {
        passwordField.sendKeys(password);
    }

    public void clickLoginButton() {
        loginButton.click();
    }
}
  • 6. В классе WikiMainPage пишем локатор для определения имени пользователя (userName) и метод (getText) для получения текста из имени. У userName нет своего id, а потому в FindBy передаем xpath. xpath — это язык запросов, с помощью которого можно обращаться к элементам страницы.
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class WikiMainPage {
    public WebDriver driver;

    public WikiMainPage(WebDriver driver) {
        PageFactory.initElements(driver, this);
        this.driver = driver;
    }

    @FindBy(xpath = "//*[@id="pt-userpage"]/a/span")
    private WebElement userName;

    public String getUserName() {
        return userName.getText();
    }
  • 7. Когда оба класса готовы, дорабатываем WikiLoginTest — добавляем импорты для работы теста и пишем тестовый метод.
import org.junit.Test;
import org.junit.Assert;
  • Метод wikiLoginTest проверяет совпадение имени пользователя с отображаемым на странице. Для этого поочередно вызываются все методы, работающие с элементами страницы. После этого сравниваем значение текста элемента (wikiMainPage.getUserName()) с переменной, в которой хранится имя пользователя (name). Аннотация @Test помечает метод как тестовый.
@Test
public void wikiLoginTest() {
    wikiLoginPage.inputName(name);
    wikiLoginPage.inputPassword(password);
    wikiLoginPage.clickLoginButton();

    Assert.assertEquals(wikiMainPage.getUserName(), name);
}
  • 8. Запускаем тест — в левом нижнем углу отобразится тестовый класс (WikiLoginTest) с удачно запущенным тестовым методом (wikiLoginTest) и временем его работы. Если тесты падают, они становятся красными.

  • Этот автотест можно доработать. Например, вынести все переменные в отдельный конфигурационный файл. Также можно отойти от явного управления драйверами (особенно если будет использован не один браузер). Для этого понадобится библиотека WebDriverManager, которая автоматизирует загрузку драйверов, поиск браузеров в системе, запуск в Docker-контейнерах. С WebDriverManager не придется каждый раз открывать браузер при вызове тестовых методов.

Готовый код можно найти тут.

Типовой фреймворк для автотестов

BDD фреймворк для автотестов на Java, использующий:

  • Selenide для тестирования Web UI
  • REST assured для тестирования REST API
  • Cucumber для написания сценариев в стиле BDD

Как начать писать WEB автотесты

1. Page Objects

В модуле autotest-web в директории src/main/java/pages находятся классы PageObjects
1.1 Каждый PageObject должен наследоваться от класса WebPage
1.2 Над классом необходимо проставить аннотацию @Name(value = «<имя страницы>»)
Пример:

@Name(value = "Google")
public class GooglePage extends WebPage {

    @Name("поле поиска")
    private SelenideElement searchField = $x("//input[@name='q']");

    @Name("результаты поиска")
    private ElementCollections results = $x(xpath);
}

2. Степы

2.1 В классе со степами необходимо объявить поле PageManager и конструктор класса следующим образом:

public class MySteps {
    private PageManager pageManager;

    public MySteps(PageManager pageManager) {
        this.pageManager = pageManager;
    }
    // steps
}
  • ссылка pageManager хранит в себе инициализированный контекст текущей страницы, с помощью которой можно достать
    элемент через value аннотации @Name элемента
  • При компиляции ссылка pageManager проинициализируется автоматически путем Dependency Injection через
    PicoContainer
  • Более подробно о подходе можно ознакомиться по
    ссылке Cucumber PicoContainer

2.2 Пример инициализации страницы:
Для того, чтобы получить доступ к элементу, нам необходимо перед этим проинициализировать PageObject
pageName — это value аннотации Name класса PageObject — в нашем примере «Google»

public void setPage(String pageName){
        WebPage page=Environment.getPage(pageName);
        pageManager.setCurrentPage(page);
        }

2.3 Теперь страница проинициализирована и получить доступ к элементам можно по его имени (value)

@Если("кликнуть на элемент {string}")
public void clickOnElement(String elementName){
        SelenideElement element=pageManager
        .getCurrentPage()
        .getElement(elementName);
        element.shouldBe(visible).click();
        }

3. Тесты

#language:ru
Функционал: Поиск гугл

  Сценарий: Открытие страницы google.com, ввод значения в поис

    * открыть url "https://www.google.ru/"
    * инициализация страницы "Google"
    * ввести в поле "поле поиска" значение "Погода в Москве"
    * на странице имеется элемент "результаты поиска"
    * кликнуть на элемент "кнопка поиска"
    * инициализация страницы "страница результатов поиска"
    * на странице присутствует текст "Погода в Москве"
  • Шаг 1 — открытие веб страницы
  • Шаг 2 — инициализация PageObject через его value аннотации @Name
  • Шаг 3 — как в примере 2.3 получаем текущий элемент по его value аннотации @Name и производим
    действия/проверки

4. Настройки

В директории autotest-web/src/test/resources/config имеются примеры config-файлов для разных браузеров.

webdriver.browser.size=1920x1080 - разрешение браузера
webdriver.browser.name=chrome  - название браузера
webdriver.timeoutSeconds=4  - таймаут ожидания состояния веб-элементов
polling.timeoutMs=200  - периодичность опроса веб-элемента
webdriver.version=91.0  - версия веб-драйвера
pages.package=pages  - пакет в котором находятся пейджи
screenAfterStep=false - необходимость аттачить скриншот к каждому шагу

По умолчанию тесты запускаются на браузере Chrome, если необходимо переопределить браузер то делаем это
через -Dbrowser=edge
Так же с помощью одноименных переменных окружения можно переопределить данные настройки
Драйвера скачиваются с помощью WebDriverManager, учитывайте это если находитесь в закрытом контуре

Как начать писать API тесты

Принцип написания тестов похож на подход создания и отправки запроса в Postman

Шаг 1. Конфигурируем запрос с помощью шага

* создать запрос
| method | path | body | url |

Если какой то из столбцов не указан в данном шаге, то он не учитывается в запросе Например:

* создать запрос
| method | path  | body            |
| POST   | /user | createUser.json |
ИЛИ
* создать запрос
| method | path  |      body        |
| POST   | /user | {<тело запроса>} |
ИЛИ
* создать запрос
| method |                  url                           |
| GET    | https://petstore.swagger.io/v2/user/<username> |
  • Можно указать basePath через одноименную системную переменную или в файле конфигурации ***
    configuration.properties***. Тогда вместо столбца url можно указывать просто path. И наоборот, если указать столбец
    url с полным url хоста и path то basePath не учитывается, даже если указан с системных переменных.
  • Тело запроса — в качестве тела можно передать в таблицу, как просто текст, так и название файла json, которое
    будет лежать по пути autotest-rest/src/test/resources/json

Шаг 2. Добавление Headers и Query

* добавить header
| Content-Type | application/json |
* добавить query параметры
| city | Moscow |

Шаг 3. Отправка запроса

Шаг 4. Проверка ответа

Если необходимо проверить тело ответа, то данные можно вытащить с помощью jsonpath. Значение сохранится в переменную из
столбца 1

* извлечь данные
| user_id | $.message |

Проверить извлеченные данные можно с помощью шага:

* сравнить значения
| ${user_id} | != | null |
ИЛИ
| ${user_id} | == | 1234567890 |
ИЛИ
| ${user_id} | > | 0 |
ИЛИ
| ${user_id} | < | 100 |
ИЛИ
| ${user_id} | содержит | qwerty123 |

Иная информация.

С помощью следующего шага можно сгенерить переменные для последующего использования в тесте

* сгенерировать переменные
| id         | 0                 |
| username   | EEEEEEEE          |
| firstName  | EEEEEEEE          |
| lastName   | EEEEEEEE          |
| email      | EEEEEEE@EEEDDD.EE |
| password   | DDDEEEDDDEEE      |

R — случайная русская буква
E — случайная английская буква
D — случайное число
Другие символы в строке игнорируются и остаются неизменяемыми Сгенерированные значения хранятся в контексте теста. Их
можно подставлять в запросы, тела запросов. Достать их можно используя синтаксис ${username}

Запуск API через консоль

mvn -am -pl autotest-rest test -Dtags=»@test» -Ddataproviderthreadcount=5

Запуск WEB через консоль

mvn -am -pl autotest-web test -Dtags=»@google» -Ddataproviderthreadcount=5

Так же запустить тесты можно через плагин Cucumber (предварительно установив его в Idea), для этого необходимо открыть
любой feature-файл, и кликнуть по зеленой стрелке рядом со стройкой Функционал или Сценарий
feature

Генерация отчета

По итогу прогонов можно сгенерить Allure отчет, для этого необходимо в Intellij Idea кликнуть на строку Maven в
правом верхнем углу IDE и следовать инструкции по пунктам ниже:
В п.1 необходимо выбрать тот модуль, в котором запускались тесты.
allure
По итогу сформируется Html страница с отчетом.
allure-report
В отчете можно провалиться в каждый шаг и посмотреть информацию по нему
allure-step

Публикуем практическую часть статьи-воркшопа о тестировании интерфейса новогоднего сайта с помощью локаторов CSS и XPath и фреймворка Selenide.

Первая, теоретическая часть статьи тут.

Другие статьи можно найти по тэгу #автоматизация

Практическая часть на Selenide

  1. Перед созданием проекта установите Maven, openjdk 1.8 или выше, IDE intellij Community.

Автоматизированное тестирование будет выполнено с помощью Selenide. Selenide – это фреймворк для автоматизированного тестирования веб-приложений на основе Selenium WebDriver.

  1. Создайте пустой проект с названием “ui-test” со следующими зависимостями в pom файле:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.example</groupId>
  <artifactId>ui-test</artifactId>
  <version>1.0-SNAPSHOT</version>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.plugin.version>3.8.1</maven.compiler.plugin.version>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
  </properties>
  <dependencies>
    <dependency>
      <artifactId>junit-jupiter</artifactId>
      <groupId>org.junit.jupiter</groupId>
      <version>5.4.2</version>
    </dependency>
    <dependency>
      <groupId>com.codeborne</groupId>
      <artifactId>selenide</artifactId>
      <version>5.25.1</version>
    </dependency>
  </dependencies>
</project>

 Создайте структуру проекта:

Каталог main в нашем примере не будет использован, все тесты и вспомогательные элементы будет находиться в каталоге test.

4. Описание локаторов для Xpath

Для этого в каталоге model создайте java-класс и назовите его “XpathLocators”. Далее в нем создайте локаторы для Selenide:

public class XpathLocators {
    public SelenideElement homePage = $(By.xpath("//img[@class='untilmerry']"));
    public SelenideElement fullHeaderButton = $(By.xpath("//a[text()='Naughty or Nice List']"));
    public SelenideElement partialHeaderButton = $(By.xpath("//a[contains(text(),'ghty or Nice')]"));
    public SelenideElement openNaughtyOrNiceListByClassAndHrefButton = $(By.xpath("//a[@href='/Den/list.asp'] [@class='home-btn']"));
    public SelenideElement tableQuestionsByPartialIdField = $(By.xpath("//form[contains(@id,'uest')]"));
    public SelenideElement headerTopByIdField = $(By.xpath("//div[@id='top']"));
    public ElementsCollection searchElementAndFilterAndClickRadioButton = $$(By.xpath("//form[@id='questions']/ul[1]//li"));
    public SelenideElement searchElementAndGoToParent = $(By.xpath("//form[@id='questions']/.."));
    public SelenideElement headerNaughtyOrNiceListPage = $(By.xpath("//img[@src='../images/den/title_list.jpg']"));
    public void approveCookieWindow(){
        SelenideElement cookieButton = $(By.xpath("//a[@href='javascript:void(0)']"));
        if (cookieButton.shouldBe(visible, Duration.ofSeconds(10)).exists()){
            cookieButton.click();
        }
    }
}

Где “SelenideElement, который возвращается методом $ — является прокси-элементом. В момент создания с помощью $ реальный элемент на странице не ищется. Зато потом при любой попытке совершить с прокси-элементом какое-то действие или проверку — прокси-элемент получает последнюю актуальную «версию» реального элемента со страницы (типа WebElement) и «проксирует» ей указанное действие или проверку.

ElementCollection — объект этого класса также является прокси точно также как SelenideElement. Его можно получить с помощью вызова метода $$, и он представляет список веб-элементов на странице.”

5. Далее в каталоге UiTest создайте java-класс “BaseTest”.

Укажите в нем 2 условия перед и после выполнения автотеста:

public class BaseTest {
    @BeforeAll
    public static void setUp() {
        Configuration.headless = false;
    }
    @AfterAll
    public static void tearDown() {
        Selenide.closeWebDriver();
    }
}

6. Далее в каталоге UiTest создайте java-класс “XpathTest” с наследованием BaseTest. 

Внутри него опишите автотесты UI с использованием xpath локаторов:

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class XpathTest extends BaseTest {
    private XpathLocators xpath = new XpathLocators();
    private static String fullHeaderButton = "Naughty or Nice List";
    @BeforeEach
    public void prepareForTest() {
        open("http://www.northpole.com/");
    }
    @Test
    @Order(1)
    @DisplayName("Переход на главную страницу c локатором по имени элемента и атрибуту класса")
    public void fullHeaderHome() {
        xpath.approveCookieWindow();
        xpath.homePage.shouldBe(visible, Duration.ofSeconds(10));
    }
    @Test
    @Order(2)
    @DisplayName("Поиск по абсолютному совпадению заголовка 'Naughty or Nice List' кнопки Naughty or Nice List")
    public void fullHeaderButton() {
        xpath.fullHeaderButton.shouldBe(visible, Duration.ofSeconds(10))
                              .shouldHave(ownText(fullHeaderButton));
    }
    @Test
    @Order(3)
    @DisplayName("Поиск по частичному совпадению заголовка 'ghty or Nice' кнопки Naughty or Nice List")
    public void partialHeaderButton() {
        xpath.partialHeaderButton.shouldBe(visible, Duration.ofSeconds(10))
                                 .shouldHave(ownText(fullHeaderButton));
    }
    @Test
    @Order(4)
    @DisplayName("Поиск кнопки по атрибуту href с проверкой перехода на страницу Naughty Or NiceList")
    public void openNaughtyOrNiceListByClassAndHrefButton() {
        xpath.openNaughtyOrNiceListByClassAndHrefButton.shouldBe(visible, Duration.ofSeconds(10))
                                                       .click();
        xpath.headerNaughtyOrNiceListPage.shouldBe(visible, Duration.ofSeconds(10));
    }
    @Test
    @Order(5)
    @DisplayName("Поиск по частичному совпадению значения атрибута")
    public void tableQuestionsByPartialIdField() {
        xpath.openNaughtyOrNiceListByClassAndHrefButton.shouldBe(visible, Duration.ofSeconds(10))
                                                       .click();
        xpath.tableQuestionsByPartialIdField.shouldBe(visible, Duration.ofSeconds(10))
                                            .click();
    }
    @Test
    @Order(6)
    @DisplayName("Поиск по id элемента")
    public void searchHeaderTopByIdField() {
        xpath.openNaughtyOrNiceListByClassAndHrefButton.shouldBe(visible, Duration.ofSeconds(10))
                                                       .click();
        xpath.headerTopByIdField.shouldBe(visible, Duration.ofSeconds(10));
    }
    @Test
    @Order(7)
    @DisplayName("Поиск по индексу в таблице, фильтр элемента по букве 'i', далее взять элемент по совпадению с индексом 0 и найти элемент input и кликнуть его")
    public void searchTextAndGoParentRadioButton() {
        xpath.openNaughtyOrNiceListByClassAndHrefButton.shouldBe(visible, Duration.ofSeconds(10))
                                                       .click();
        xpath.searchElementAndFilterAndClickRadioButton.filterBy(text("i"))
                                                       .get(0)
                                                       .find(By.xpath("./input"))
                                                       .click();
    }
    @Test
    @Order(8)
    @DisplayName("Поиск элемента по id, далее переход к его родителю и сравнение ожидаемого результата")
    public void searchElementAndGoToParent() {
        xpath.openNaughtyOrNiceListByClassAndHrefButton.shouldBe(visible, Duration.ofSeconds(10))
                                                       .click();
        xpath.searchElementAndGoToParent.getId().contains("naughtynice");
    }
}

При описании автотестов выполнялись проверки состояния элементов shouldBe() с ключами visible и Duration.ofSeconds(), они означают, что элемент должен был отображаться на странице, появиться элемент должен был в течении 10 секунд (Duration.ofSeconds(10)), если это будет выполнено ранее 10 сек, то выполняется следующая операция.

На некоторые элементы выполняется клик с помощью команды .click. С доступными командами для SelenideElement можно ознакомиться тут.

7. Запустить автотесты локально можно следующими способами:

  1. Запуск автотестов через терминал, используя maven и команды mvn clean install из каталога {folder_project}/ui-test
  2. Запустить автотесты из вкладки Maven
  3. Запустить автотесты в java-классе используя junit фреймворк.

Результат прогона:

8. Повторим тоже самое для css локаторов. Для этого в каталоге model создадим java-класс и назовем его CssLocators:

public class CssLocators {
    public SelenideElement homePage = $(By.cssSelector("img[class='untilmerry']"));
    public SelenideElement fullHeaderButton = $(By.cssSelector("a[href='/Den/list.asp'][class='home-link']"));
    public SelenideElement partialHeaderButton = $(By.cssSelector("a[href='/Den/list.asp'][class*='-link']"));
    public SelenideElement openNaughtyOrNiceListByClassAndHrefButton = $(By.cssSelector("a[href='/Den/list.asp'][class='home-btn']"));
    public SelenideElement tableQuestionsByPartialIdField = $(By.cssSelector("form[id*='uest']"));
    public SelenideElement headerTopByIdField = $(By.cssSelector("#top "));
    public ElementsCollection searchElementAndFilterAndClickRadioButton = $$(By.cssSelector("#questions > ul:nth-child(1) > li"));
    public SelenideElement headerNaughtyOrNiceListPage = $(By.cssSelector("img[src='../images/den/title_list.jpg']"));
    public void approveCookieWindow(){
        SelenideElement cookieButton = $(By.cssSelector("a[onclick='javascript:setnocookiecookie()']"));
        if (cookieButton.shouldBe(visible, Duration.ofSeconds(10)).exists()){
            cookieButton.click();
        }
    }
}

9. Далее в каталоге UiTest создадим java-класс “CssTest” с наследованием BaseTest. Внутри него опишем автотесты UI с использованием css локаторов:

public class CssTest extends BaseTest {
    private CssLocators cssLocators = new CssLocators();
    private static String fullHeaderButton = "Naughty or Nice List";
    @BeforeEach
    public void prepareForTest() {
        open("http://www.northpole.com/");
    }
    @Test
    @Order(1)
    @DisplayName("Переход на главную страницу c локатором по имени элемента и атрибуту класса")
    public void fullHeaderHome() {
        cssLocators.approveCookieWindow();
        cssLocators.homePage.shouldBe(visible, Duration.ofSeconds(10));
    }
    @Test
    @Order(2)
    @DisplayName("Поиск по абсолютному совпадению заголовка 'Naughty or Nice List' кнопки Naughty or Nice List")
    public void fullHeaderButton() {
        cssLocators.fullHeaderButton.shouldBe(visible, Duration.ofSeconds(10))
                                    .shouldHave(ownText(fullHeaderButton));
    }
    @Test
    @Order(3)
    @DisplayName("Поиск по частичному совпадению заголовка 'ghty or Nice' кнопки Naughty or Nice List")
    public void partialHeaderButton() {
        cssLocators.partialHeaderButton.shouldBe(visible, Duration.ofSeconds(10))
                                       .shouldHave(ownText(fullHeaderButton));
    }
    @Test
    @Order(4)
    @DisplayName("Поиск кнопки по атрибуту href с проверкой перехода на страницу Naughty Or NiceList")
    public void openNaughtyOrNiceListByClassAndHrefButton() {
        cssLocators.openNaughtyOrNiceListByClassAndHrefButton.shouldBe(visible, Duration.ofSeconds(10))
                                                             .click();
        cssLocators.headerNaughtyOrNiceListPage.shouldBe(visible, Duration.ofSeconds(10));
    }
    @Test
    @Order(5)
    @DisplayName("Поиск по частичному совпадению значения атрибута")
    public void tableQuestionsByPartialIdField() {
        cssLocators.openNaughtyOrNiceListByClassAndHrefButton.shouldBe(visible, Duration.ofSeconds(10))
                                                             .click();
        cssLocators.tableQuestionsByPartialIdField.shouldBe(visible, Duration.ofSeconds(10))
                                                  .click();
    }
    @Test
    @Order(6)
    @DisplayName("Поиск по id элемента")
    public void searchHeaderTopByIdField() {
        cssLocators.openNaughtyOrNiceListByClassAndHrefButton.shouldBe(visible, Duration.ofSeconds(10))
                                                             .click();
        cssLocators.headerTopByIdField.shouldBe(visible, Duration.ofSeconds(10));
    }
    @Test
    @Order(7)
    @DisplayName("Поиск по индексу в таблице, фильтр элемента по букве 'i', далее взять элемент по совпадению с индексом 0 и найти элемент input и кликнуть его")
    public void searchTextAndGoParentRadioButton() {
        cssLocators.openNaughtyOrNiceListByClassAndHrefButton.shouldBe(visible, Duration.ofSeconds(10))
                                                             .click();
        cssLocators.searchElementAndFilterAndClickRadioButton.filterBy(text("i"))
                                                             .get(0)
                                                             .find(By.xpath("./input"))
                                                             .click();
    }
}

10. Повторим запуск всех написанных тестов удобным вам способом.

Результаты следующие:

XPath позволяет перемещаться по дереву вниз и вверх, дает возможность использовать оси элементов. Бытует мнение, что поиск элемента с помощью xpath выполняется дольше чем css, но по факту незначительно (либо нужно пересмотреть локатор xpath). Подробнее почитать про xpath можно тут.

CSS – короткий при написании, достаточно читабельный, имеет ограничение по переходу от родителя к ребенку (но не от ребенка к родителю). Подробнее почитать по css можно тут.

Понравилась статья? Поделить с друзьями:
  • Как написать автору на ао3
  • Как написать автору на автор 24
  • Как написать автору на ao3
  • Как написать автору канала на яндекс дзен
  • Как написать авторскую статью