Смок-тестирование релиз-кандидата автотестами за 15 минут

Меня зовут Лилия, я QA Lead в одном из проектов финансовой группы БКС (сервис по подбору выгодных для клиента предложений из ряда кредитных продуктов), и сегодня я расскажу, как мы автоматизировали смок-тестирование, с какими проблемами столкнулись и какой стек технологий используем.

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

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

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

На нашем проекте:

  • Регистрация/авторизация.
  • Вход.
  • Заполнение анкеты.
  • Витрина предложений.
  • Отправка заявки/переход по ссылке на сайт партнера.
  • Обратная связь.
  • Блокировка.

Стек технологий для написания автотестов

Автотесты мы пишем на вот таком стеке: Java + Selenium + Cucumber + отчеты в Allure2.

image

BDD Автотесты для смок-тестирования

1. Фича файл с расширением .feature с описанием сценариев тестов на языке Gerkin.

Пример:

Функция: Проверка профиля, личного кабинета и заявок   @all   Сценарий: Проверка блоков на странице профиля     Дано Перейти на страницу Главная в приложении     Когда Главная: Нажимаю на ссылка Войти     И Вход: Ввожу в поле Телефон значение **********     И Вход: Нажимаю на кнопка Получить код     И Вход: Ввожу в поле Код подтверждения значение ****     И Главная: Навожу курсор на элемент ссылка Меню пользователя     И Главная: Нажимаю на ссылка Профиль     Тогда Происходит переход на страницу Профиль     Тогда Профиль: Отображается элемент заголовок Регистрационные данные     Тогда Профиль: Отображается элемент заголовок Паспортные данные     Тогда Профиль: Отображается элемент заголовок Адрес регистрации     Тогда Профиль: Отображается элемент заголовок Адрес проживания     Тогда Профиль: Отображается элемент заголовок Сведения о трудоустройстве  

2. Шаги steps. В нем находятся классы, в которых описаны действия с элементами на странице и проверки этих элементов.

Пример:

@When("^Нажимаю клавишу (.*)")     public void pressKey(String key)  {         webElementUtils.pressKey(key);     }     @When("^(.*): Нажимаю на (.*)")     public void press(String pageTitle, String elementName)  {         waitUtils.waitElementToBeClickable(getWebElementOnWebPageWithWaiter(elementName, pageTitle)).click();     }     @When("^(.*): Ставлю отметку на (.*)")     public void checkCheckbox(String pageTitle, String elementName) {         WebElement element = getWebElementOnWebPageWithWaiter(elementName, pageTitle);         if (!webElementUtils.isCheckboxSelected(element)) {             element.click();         }     }     @When("^(.*): Снимаю отметку с (.*)")     public void uncheckCheckbox(String pageTitle, String elementName) {         WebElement element = getWebElementOnWebPageWithWaiter(elementName, pageTitle);         if (webElementUtils.isCheckboxSelected(element)) {             element.click();         }     }     @And("^(.*): Стираем значение в (.*)$")     public void erase(String pageTitle, String elementName) {         WebElement element = getWebElementOnWebPageWithWaiter(elementName, pageTitle);         webElementUtils.clearElement(element);     }     @And("^(.*): Ввожу в (.*) значение (.*)$")     public void enterValue(String pageTitle, String elementName, String text) {         WebElement element = getWebElementOnWebPageWithWaiter(elementName, pageTitle);         webElementUtils.fillElementWithText(element, expressionUtils.parseString(text));     }     @And("^(.*): в (.*) выбрать (.*)$")     public void selectValue(String pageTitle, String dropdownListName, String value) {         WebElement element = getWebElementOnWebPageWithWaiter(dropdownListName, pageTitle);         webElementUtils.selectValueFromCombobox(element, value);     }     @Then("^(.*): в (.*) отсутствует текст$")     public void elementDoesNotContainAnyText(String pageTitle, String elementName) {         WebElement element = getWebElementOnWebPageWithWaiter(elementName, pageTitle);         assertEquals("", webElementUtils.getTextFromWebElement(element).trim());     }     @Then("^(.*): ползунок (.*) находится в положении (.*)$")     public void checkSliderPosition(String pageTitle, String elementName, String expectedPosition) {         WebElement element = getWebElementOnWebPageWithWaiter(elementName, pageTitle);         String sliderTrackPosition = StringUtils.substringBetween(element.findElement(By.cssSelector(".rc-slider-track")).getAttribute("style"), "width: ", ";");         String sliderHandlePosition = StringUtils.substringBetween(element.findElement(By.cssSelector(".rc-slider-handle")).getAttribute("style"), "left: ", ";");         assertEquals(expectedPosition, sliderTrackPosition);         assertEquals(expectedPosition, sliderHandlePosition);     }     @Then("^(.*): Отображается компонент (.*)$")     public void checkComponentIsDisplayed(String pageTitle, String component) {         WebElement element = getWebElementOnWebPageWithWaiter(component, component);         assertTrue(webElementUtils.isElementVisible(element));     }     @When("^(.*): Загружаю файл (.+) в (.*)$")     public void loadFileInField(String pageTitle, String fileName, String elementName) {         WebElement element = getWebElementOnWebPage(elementName, pageTitle);         File file = new File(Objects.requireNonNull(getClass().getClassLoader().getResource(fileName)).getFile());         element.sendKeys(file.getAbsolutePath());     }     @Then("^(.+): У элемента (.+) атрибут (.+) имеет значение (.+)$")     public void checkAttributeInElement(String pageTitle, String elementName, String attributeName, String expectedValue) {         WebElement element = getWebElementOnWebPage(elementName, pageTitle);         String attribute = webElementUtils.getAttribute(element, attributeName);         String message = String.format("Атрибут '%s' у элемента '%s' на странице '%s' не соответствует ожидаемому значению.\n" +                 "Ожидаемое значение: '%s'.\nФактическое значение: '%s'.\n", attributeName, elementName, pageTitle,                 expectedValue, attribute);         assertEquals(message, expectedValue, attribute);     }     @Then("^(.+): У элемента (.+) значение (.+)/$")     public void checkValueTag(String pageTitle, String tagName, String expectedValue) {         WebElement title = webDriver.findElement(By.tagName(tagName));         assertEquals(expectedValue, title.getAttribute("innerHTML").trim());     } }

3. Работа с локаторами на страницах (паттерн PageObject)

Пример:

import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import ru.bcs.creditmarkt.acceptance.pageobject.annotation.PageObject; import ru.yandex.qatools.htmlelements.annotations.Name; @PageObject(title = "Вход", path = "/entry/login") public class LoginPage extends WebPage {     @Name("ссылка Регистрация")     @FindBy(xpath = "//a[text()='Регистрация']")     private WebElement registrationLink;     @Name("ссылка Вход")     @FindBy(xpath = "//a[text()='Вход']")     private WebElement loginLink;     @Name("поле Телефон")     @FindBy(css = "#phone")     private WebElement phoneInput;     @Name("кнопка Получить код")     @FindBy(css = "button[type=submit]")     private WebElement receiveCodeButton;     @Name("поле Код подтверждения")     @FindBy(css = "input#sms")     private WebElement smsInput;     @Name("чекбокс Согласен с условиями обработки персональных данных")     @FindBy(css = "button#personalAgreement")     private WebElement personalAgreementCheckbox;     @Name("иконка Чат-бот")     @FindBy(css = "div.wa-userpic")     private WebElement chatBotIcon; }

4. Отчет в Allure2

image

Настройка CI

Пока мы писали автотесты, у финансовой группы БКС появился Selenoid, и мы смогли настроить запуск тестов в pipline GitLab

Организация написания автотестов для разных стендов

У нас есть несколько стендов, на которых и происходит разработка, отладка, приемка, а еще есть очень много feature-стендов, где мы тестируем новые функции, разрабатываемые распределенными командами.

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

Итого

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


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

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

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