Как мы внедряли Allure TestOps в стриминговом сервисе

от автора

Всем привет! Меня зовут Иван Чечиков, я QA lead в МТС Digital, работаю над проектом стримингового сервиса WASD.TV. В этой статье я поделюсь опытом внедрения системы управления тестированием (TMS) Allure TestOps в наш проект и расскажу, что из этого получилось. А еще отмечу подводные камни, с которыми мы столкнулись и обозначу пути их обхода. Статья может быть полезна тем, кто задумываются о переходе на данную TMS с других готовых решений, таких так Zephyr, TestRail, Test IT.

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

В нашем проекте для QA мы используем Jira Server, Confluence, Jenkins CI/CD, автотесты на Java + Maven + Cucumber + Gherkin + Serenity RestAssured (для API тестов) и Selenium (для UI тестов). Как основную TMS применяли плагин Zephyr для Jira, но нам предстоял переезд на Allure Test Ops. Что делать в таком случае?

  1. Нужно настроить интеграцию с Jira Server и Allure TestOps.

  2. Нужно перенести существующие тестовые артефакты из надстройки Zephyr в Jira в Allure TestOps и уйти в дальнейшем от Zephyr.

  3. Нужно настроить запуск автотестов в Allure TestOps, подружив его с нашей джобой в Jenkins CI/CD и получать результаты прогонов. На данный момент мы работаем с Gitlab CI/CD, но опыт с Jenkins был также уникален для нас.

  4. Объединить ручные и автотесты в один проект в Allure TestOps.

  5. Написать инструкции для QA-инженеров по использованию Allure Test Ops

  6. Начать работать в Allure TestOps.

  7. Собрать первые метрики по проделанной работе.

Разберем каждый этап подробно:

Интеграция с Jira Server или Jira Cloud – дело несложное, выполняется как на стороне Allure, так и на стороне Jira. Создаем интеграцию с Jira в Allure TestOps, указываем креды и эндпоинт Jira Server.

Allure TestOps

В Jira в панели Администратора необходимо установить плагин Allure TestOps for JIRA

Указываем эндпоинты Allure Test Ops, выбираем версию 4.x.x и проставляем id интеграции Jira в Allure. Ссылка на официальный мануал.

Jira Server

Единственное замечание – желательно иметь актуальную версию Jira не ниже 8.4 (Jira Server) и Allure TestOps не ниже 4.2.2, иначе интеграция может быть неполноценной, у нас, к примеру, не отображались прогоны с Allure в Jira.

Результаты интеграции: отображение прогонов и тестовой документации из Allure в Jira.

Кейсы из плагина Zephyr в Jira мы переносили через скрипт Qameta, для нас его существование было неочевидным, поэтому пришлось писать в поддержку. Скрипт лежит на сайте у разработчиков, миграцию мы делали на удаленной машине, имеющей доступы к эндпоинтам Allure и Jira. Вызывали скрипт, передавая json в виде конфига.

java -jar allure-testops-migration-2.9.5.jar config

Проблем с миграцией не было. Все наши 2000 с лишним кейсов мигрировали в Test Cases Allure TestOps, все поля тестовых артефактов были перенесены.

Интеграция с Jenkins CI/CD заняла значительное количество времени. Проблемы были как с самой джобой дженкинса, так и с конфигурацией кода проекта. Подружить Jenkins и Allure TestOps на уровне интеграции не так сложно.

В Jenkins CI/CD в разделе плагинов устанавливаем плагин Allure TestOps for Jenkins последней версии. Это важно, так как может не произойти выгрузка результатов автотестов в Allure TestOps.

Jenkins

В настройках системы в Jenkins указываем эндпоинт Allure TestOps и админские креды.

В Allure Test Ops прописываем эндпоинт Jenkins.

У нас автотесты на Java с использованием Maven, Cucumber, Gherkin, Serenity и Selenium. Для получения результатов в Allure с прогонов автотестов пришлось править конфигурационный файл pom.xml. Я добавил зависимости:

pom.xml

<dependencies> ......   <dependency>     <groupId>io.qameta.allure</groupId>     <artifactId>allure-junit4-aspect</artifactId>     <version>2.0-BETA15</version>   </dependency>   <dependency>     <groupId>io.qameta.allure</groupId>     <artifactId>allure-rest-assured</artifactId>     <version>2.18.1</version>   </dependency>   <dependency>     <groupId>io.qameta.allure</groupId>     <artifactId>allure-cucumber5-jvm</artifactId>     <version>2.18.0</version>   </dependency> ......   <build>         <plugins>             <plugin>                 <groupId>org.apache.maven.plugins</groupId>                 <artifactId>maven-surefire-plugin</artifactId>                 <version>3.0.0-M4</version>                 <configuration>                   <forkCount>3</forkCount>                     <reuseForks>true</reuseForks>                     <argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>                     <testFailureIgnore>true</testFailureIgnore>                     <includes>                         <include>**/*${type.of.suite}.java</include>                     </includes>                     <systemPropertyVariables>                         <webdriver.base.url>${webdriver.base.url}</webdriver.base.url>                         <allure.results.directory>${project.build.directory}/allure-results</allure.results.directory>                     </systemPropertyVariables>                     <parallel>classes</parallel>                     <threadCount>${parallel.tests}</threadCount>                     <forkCount>${parallel.tests}</forkCount>                 </configuration>                 <dependencies>                     <dependency>                         <groupId>org.aspectj</groupId>                         <artifactId>aspectjweaver</artifactId>                         <version>1.7.4</version>                     </dependency>                 </dependencies>                 <executions>                     <execution>                         <goals>                             <goal>test</goal>                         </goals>                     </execution>                 </executions>           </plugin>       </plugins>   </build>

Чтобы все это добро заработало в Cucumber – пришлось прописывать плагины для API и Ui-классов.

ApiCucumberTestSuite.java

package starter.runner.api;  import io.cucumber.junit.Cucumber;  import io.cucumber.junit.CucumberOptions;  import org.junit.runner.RunWith;   @RunWith(Cucumber.class)  @CucumberOptions(            plugin = {"io.qameta.allure.cucumber5jvm.AllureCucumber5Jvm"},            features = "src/test/resources/features/api/",            glue = {"starter"} )  public class ApiCucumberTestSuite {}

UiCucumberTestSuite.java

package starter.runner.ui;  import io.cucumber.junit.Cucumber;  import io.cucumber.junit.CucumberOptions;  import org.junit.runner.RunWith;  @RunWith(Cucumber.class)  @CucumberOptions(          plugin = {"io.qameta.allure.cucumber5jvm.AllureCucumber5Jvm"},            features = "src/test/resources/features/ui/",            glue = {"starter"} )  public class UiCucumberTestSuite {}

Для определения типов тестов добавил аннотации allure.label.layer в features файлы.

authorizationApi.feature

@auth @api @all @smoke @allure.label.layer=Api  Функция: Авторизация    Пользователь делает авторизацию через API    @positive @api    Структура сценария: успешная авторизация      Когда <User> делает авторизацию через API      Тогда пользователь получает access token      Примеры:        | User  |        | user1 |

authorizationUi.feature

@auth @ui @all @allure.label.layer=Ui  Функция: Авторизация    Пользователь авторизуется    @positive @ui    Структура сценария: успешная авторизация      Дано пользователь переходит на главную страницу      Когда пользователь авторизуется под юзером <User>      Тогда пользователь проверяет, что отображается имя юзера <User>      Примеры:        | User  |        | user1 |        | user3 |

Для логирования API тестов через SerenityRest в Allure TestOps добавил в коде в респонсы фильтр с AllureRestAssured.

ApiAuthorizationStepDefinitions.java

......    JSONObject requestBody = new JSONObject();    requestBody.put("user_email", user_email);    requestBody.put("user_password", user_password);    response = SerenityRest.given().filter(new AllureRestAssured()).log().all().    and().    body(requestBody.toMap()).    contentType(ContentType.JSON).    post(EndPoints.tokens);  ......

Для логирования UI-тестов через Selenium в Allure TestOps добавил в коде шаги с получением скрина текущей страницы с помощью класса AllureForScreenshot.

AllureForScreenshot.java

package allure;  import io.qameta.allure.Allure;  import org.openqa.selenium.OutputType;  import org.openqa.selenium.TakesScreenshot;  import org.openqa.selenium.WebDriver;  import java.io.File;  import java.io.FileInputStream;  import java.io.FileNotFoundException;  public class AllureForScreenshot {      public void takeScreenshot(WebDriver webDriver) throws FileNotFoundException {          File screenshotAs = ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.FILE);          Allure.addAttachment("Screenshot", new FileInputStream(screenshotAs));      }  }

UiAuthorizationStepDefinitions.java

......  switch (user) {              case "user1":                  allureForScreenshot.takeScreenshot(mainPage.getDriver());                  mainPage.openAuthForm();                  allureForScreenshot.takeScreenshot(authorizationPage.getDriver());                  authorizationPage.fillEmailField(user1Email);                  allureForScreenshot.takeScreenshot(authorizationPage.getDriver());                  authorizationPage.clickAuthLoginButton();                  allureForScreenshot.takeScreenshot(authorizationPage.getDriver());                  authorizationPage.clickPasswordButton();                  allureForScreenshot.takeScreenshot(authorizationPage.getDriver());                  authorizationPage.fillPassField(user1Pass);                  allureForScreenshot.takeScreenshot(authorizationPage.getDriver());                  authorizationPage.clickOnEnterButton();                  break;  ......

Результаты работы API и UI-тестов:

С джобой в Jenkins пришлось повозиться. Она была не параметризированная, параметры задавались на каждом шаге, логика работы билда лежала в Jenkinsfile. Allure TestOps не умеет работать с такими сборками, так как при запуске джобы из Allure она тупо висела в Jenkins на первом шаге, ожидая в интерфейсе ввода значения. Решение было простым – переписать логику Jenkinsfile под параметризированную сборку и поменять тип билда в Jenkins.

Jenkins

Jenkinsfile

pipeline {    agent any    parameters {      gitParameter branchFilter: 'origin/(.*)', defaultValue: '', name: 'BRANCH', type: 'PT_BRANCH'      choice(name: 'TEST_SUITE', choices: ['TestSuite', 'Parallel'], description: 'Выберите способ запуска тестов')      choice(name: 'TYPE_OF_TESTS', choices: ['@api', '@ui'], description: 'Выберите тип тестов')      choice(name: 'MODULE_OF_TESTS', choices: ['Список модулей тестов через @'],          description: 'Выберите модуль тестов')      choice(name: 'ENV_1', choices: ['Список тестовых стендов'],       description: 'Выберите стенд')    }    stages {      stage("Run tests") {        steps {          script {            def inptext = readFile file: "serenity.properties"           inptext = inptext.replaceAll("env1", "${params.ENV_1}")           writeFile file: "serenity.properties", text: inptext           sh """ls ./"""           wrap([$class: 'Xvfb', additionalOptions: '', assignedLabels: '', displayNameOffset: 3, installationName:            'xvfb', parallelBuild: true, screen: '1600x1200x24']) {             sh 'printenv'             sh """mvn clean verify -Dcucumber.options=\"--tags '${params.MODULE_OF_TESTS} and ${params.TYPE_OF_TESTS}'\" -Denvironment=${params.ENV_1} -Dtype.of.suite=${params.TEST_SUITE}"""           }          }        }      }    }    post {      always {        withAllureUpload(indexExistingFiles: true, serverId: 'Id сервера в Allure TestOps', projectId: 'Номер проекта в Allure TestOps',          results: [            [path: 'target/allure-results']          ]) {        }      }    }  }

Результаты прогона отправляются на последнем этапе работы билда. Внешний вид прогонов в Jenkins:

Джоба в Allure TestOps имеет вид:

Мы запускаем билд через параметры в environment. Это удобно, так как можно создать значения в данной форме, которые будут выбираться из выпадающего списка, исключая повторный ввод вручную. Есть нюанс с дефолтными полями: Device, OS, Host, Browser, Environment – к сожалению, их нельзя удалить либо отключить, если они не используются. Приходится игнорировать их при запуске джобы.

Внешний вид прогона в Allure TestOps:

Под ручные и авто тесты я создал один общий проект.

Разделил в фильтрах ручные тестовые артефакты по командам, внутри каждой команды тест кейсы и чек-листы разделены по функционалу. Автоматизированные кейсы лежат в отдельных фильтрах (API, UI). В ближайшем будущем планирую также разделить их по командам.

Разделил в фильтрах ручные тестовые артефакты по командам, внутри каждой команды тест кейсы и чек-листы разделены по функционалу. Автоматизированные кейсы лежат в отдельных фильтрах (API, UI). В ближайшем будущем планирую также разделить их по командам.

В Allure TestOps по дефолту три уровня вложенности и есть шаблон под тестовые артефакты (тест-кейсы, чек-листы).

В самом тестовом артефакте можно:

  • проставлять различные тэги;

  • линковать его с тасками в багтрекере;

  • писать в нем комментарии 

  • прикреплять файлы и изображения;

  • вешать различные роли (владелец, ревьювер и прочие, в зависимости от флоу тестирования); 

  • менять его статусы; 

  • создавать с ним ручные и авто прогоны, линковать их в той же Jira, выполнять по шагам, проставляя статусы (Passed, Failed, Skipped и прочие).

Также присутствует возможность заведения дефектов параллельно с созданием сущностей в Jira.

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

Инструкции мы создали в Confluence, провели QA-ретро и познакомились всем отделом качества с функционалом Allure TestOps.

Начали работать с Allure. Наш флоу: анализ задачи, написание тестовой документации, командное кроссревью, созданного тестового артефакта, ручное тестирование, автоматизированное тестирование (смоук, регресс), деплой. Какие трудности мы испытали: 

  • нельзя переносить папки с тестовыми артефактами в интерфейсе Allure;

  • заведение дефектов параллельно с созданием задач в Jira вызывает дискомфорт, так как требуется переход в баг-трекер для дозаполнения тасок;

  • не хватает почтовых уведомлений при ревью тестовой документации, да и вообще для любых изменений в TMS;

  • в нашем случае для запуска джобы автотестов было бы удобно создавать несколько environments, тем самым запуская за раз несколько билдов в Jenkins, но у нас так не работает;

  • не хватает аналитики по заведенным дефектам

  • хотелось бы метрики с дашбордов экспортировать в pdf для передачи отчетов заинтересованным лицам

Прошел спринт и я собрал первые метрики по проделанной работе QA-отдела. Для этого в Allure TestOps можно создавать отдельные дашборды на главной странице проекта и с помощью AQL помещать в них диаграммы по сущностям Allure. Результаты радуют, QA активно работают в новой TMS, выполняют ручные и автоматизированные прогоны, заводят дефекты. Чего не хватает для сбора аналитики: AQL для заведенных в Allure TestOps багов и их параметров, но вроде бы Qameta скоро релизнет такой функционал.

Итог: с момента самостоятельного внедрения Allure TestOps до запуска проекта и начала работы в нем прошло порядка двух месяцев. Большое спасибо компании Qameta за предоставленный продукт, а команде поддержке за своевременную и полноценную помощь. Мы получили уникальный и полезный опыт при работе с продуктом. Ждем с нетерпением новых релизов и пользуемся тем, что уже есть!

Спасибо за уделенное время, если у вас есть вопросы – буду рад на них ответить в комментариях.


ссылка на оригинал статьи https://habr.com/ru/company/ru_mts/blog/689330/


Комментарии

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

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