Pull to refresh
1748.06
МТС
Про жизнь и развитие в IT

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

Reading time11 min
Views17K

Всем привет! Меня зовут Иван Чечиков, я 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). В ближайшем будущем планирую также разделить их по командам.

В 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 за предоставленный продукт, а команде поддержке за своевременную и полноценную помощь. Мы получили уникальный и полезный опыт при работе с продуктом. Ждем с нетерпением новых релизов и пользуемся тем, что уже есть!

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

Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
Total votes 5: ↑4 and ↓1+4
Comments4

Articles

Information

Website
www.mts.ru
Registered
Founded
Employees
over 10,000 employees
Location
Россия