Azure DevOps для QA: как организовать запуск автотестов и разбор ошибок

13 ноября 2026 • Павел Калабин

Когда автотесты теряют часть своей ценности? Когда запускаются в разных pipeline, результаты хранятся в разных местах, а для разбора ошибки приходится собирать информацию по частям. Мы выстроили процесс тестирования в Azure DevOps, который объединяет запуск тестов, публикацию отчётов, связь с тест-кейсами и хранение артефактов. 

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

Как устроена работа с автотестами в Azure DevOps

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

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

Мы решаем эти задачи с помощью Azure DevOps – платформы для организации процессов разработки и тестирования.

В нашем решении несколько инструментов отвечают за разные части процесса:

  • Azure Pipelines запускает автоматические проверки и выполняет вспомогательные операции.

  • Test Plans помогает организовать тестовую документацию: планы, наборы проверок и тест-кейсы.

  • Azure Artifacts хранит версии пакетов, которые используются в разных запусках. В нашем случае это пакет с эталонными скриншотами.

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

Разберём, как устроены эти механизмы и какую задачу решает каждый из них.

1. Запускаем нужные наборы автотестов

Azure Pipelines позволяет автоматизировать последовательность действий: подготовить окружение, запустить тесты и сохранить результаты. Такая последовательность называется pipeline, или конвейером.

Pipeline можно разделить на stages – этапы выполнения. В нашем проекте функциональные E2E-тесты на Cypress выполняются отдельно от UI-тестов на Playwright.

Разделение тестов на этапы позволяет запускать нужный набор независимо от остальных проверок, если это предусмотрено конфигурацией pipeline. Например, после изменения интерфейса можно запустить UI-тесты, не дожидаясь выполнения всех остальных сценариев.

общий статус pipeline и состояние отдельных stages

(общий статус pipeline и состояние отдельных stages)

При ручном запуске через Run pipeline выбираем ветку с нужной версией кода и задаём параметры запуска. Возможность выбирать отдельные stages зависит от конфигурации pipeline и доступных параметров.

форма ручного запуска pipeline и выбор параметров

(форма ручного запуска pipeline и выбор параметров)

Дополнительные зависимости нужно обеспечить заранее: например, это могут быть тестовые данные или результаты предыдущего этапа.

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

2. Следим за выполнением тестов через логи

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

В Azure Pipelines тесты запускаются внутри задач, которые объединяются в этапы. Задача или job – это отдельная единица выполнения, содержащая один или несколько шагов.

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

логи выполнения UI-тестов в Azure DevOps

(логи выполнения UI-тестов в Azure DevOps)

Например, тест не смог авторизоваться в приложении. Значит мы смотрим в логах: открылась ли страница входа, были ли выполнены необходимые действия, на каком шаге остановился сценарий?

Мы используем логи как первый уровень диагностики. Для более подробного разбора сохраняем результаты тестов, скриншоты и записи выполнения сценариев.

3. Публикуем результаты и разбираем ошибки

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

Для этого тестовый раннер формирует отчёт в поддерживаемом формате. Мы используем JUnit XML — структурированный файл, содержащий результаты тестов, их статусы и информацию об ошибках.

Чтобы Azure DevOps показал эти результаты на вкладке Tests, публикуем файл с помощью задачи PublishTestResults@2:

task: PublishTestResults@2

displayName: "Publish UI test results"

condition: succeededOrFailed()

inputs:

testResultsFormat: JUnit

testResultsFiles: '**/test-results.xml'

Что означают эти настройки:

  • testResultsFormat: JUnit указывает формат отчёта.

  • testResultsFiles задаёт путь к файлу с результатами. Шаблон **/test-results.xml позволяет искать файлы с таким именем в подкаталогах рабочего каталога.

  • condition: succeededOrFailed() позволяет выполнить публикацию, если предыдущие шаги завершились успешно или с ошибкой. Это помогает сохранить результаты даже после неудачного прогона тестов.

04

Путь к файлу должен соответствовать расположению отчёта на агенте, который выполняет pipeline. После публикации результаты становятся доступны на вкладке Tests соответствующего запуска.

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

 (сводка результатов тестирования с количеством пройденных и упавших тестов)

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

список тестов со статусами Passed и Failed

(список тестов со статусами Passed и Failed)

детали упавшего теста и сообщение об ошибке

(детали упавшего теста и сообщение об ошибке)

Для детального разбора проблем мы формируем HTML-отчёт и сохраняем диагностические материалы: Playwright-скриншоты и trace-файлы.

В Trace хранится запись выполнения теста, информация о последовательности действий и состоянии страницы.

Для формирования HTML-отчёта используем отдельный PowerShell-скрипт:

task: PowerShell@2 

displayName: "Create Playwright failure HTML report"

inputs:

targetType: filePath

filePath: '$(Build.SourcesDirectory)/create-playwright-failure-summary.ps1'

condition: failed()

Здесь PowerShell@2 запускает скрипт, который формирует HTML-отчёт. Переменная $(Build.SourcesDirectory) указывает на каталог с исходным кодом проекта на агенте

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

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

Если отчёт показывает изображения рядом, команда может сравнить ожидаемое состояние интерфейса с фактическим. Например, увидеть, что элемент сместился, текст изменился или нужный блок не появился.

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

4. Связываем автотесты с тест-кейсами в Test Plans

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

Для этого в Azure DevOps есть Test Plans, где хранятся сценарии проверок.

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

Test Plans с тест-планом, наборами тестов и тест-кейсами

(Test Plans с тест-планом, наборами тестов и тест-кейсами)

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

Важно: публикация JUnit сама по себе не устанавливает такое соответствие. Для того, чтобы ее настроить нужно добавить отдельный шаг в pipeline.

В нашем проекте для интеграции используется задача Create test run with test cases@0:

task: Create test run with test cases@0

displayName: "Create Playwright test run with test cases"

inputs:

buildId: "$(Build.BuildId)"

testPlanId: "390958"

В настройках задачи нужно указать два параметра:

  • testPlanId — ID тест-плана, в котором находятся нужные UI-тест-кейсы. Его можно скопировать в верхней части страницы Test Plans в Azure DevOps.

  • buildId — ID текущего запуска pipeline. Он передаётся автоматически через переменную $(Build.BuildId).

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

Так Azure DevOps сможет связать результаты выполнения автотестов с тест-кейсами в Test Plans.

5. Обновляем эталонные скриншоты через отдельный pipeline

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

Эталонный скриншот – это изображение интерфейса, с которым сравнивается снимок, полученный во время теста.

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

Например, в нашем решении предусмотрены два режима:

  • specific – обновить эталоны для выбранных тест-кейсов;

  • all – обновить весь набор.

В режиме specific можно указать один идентификатор или несколько, разделённых запятыми.

форма запуска pipeline с выбором режима и ID тест-кейсов

(форма запуска pipeline с выбором режима и ID тест-кейсов)

Перед выполнением операции pipeline должен проверить параметры. Если выбран режим specific, но идентификаторы не указаны, запуск следует остановить с понятным сообщением об ошибке.

У ручного pipeline есть и практическое преимущество: операция выполняется по одному сценарию в подготовленном окружении. В случае со скриншотами мы создаём эталоны на том же агенте, где затем сравниваем их с интерфейсом. Это уменьшает влияние различий между рабочими ПК QA-инженеров: версиями браузера, шрифтов и настроек окружения. 

6. Храним версии эталонных скриншотов в Azure Artifacts

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

Для этого мы используем Azure Artifacts – компонент Azure DevOps для хранения и распространения пакетов.

Пакет – это набор файлов, который можно опубликовать, присвоить ему версию и использовать повторно. В нашем случае эталонные скриншоты упакованы в npm-пакет.

npm – менеджер пакетов. С его помощью можно получать необходимые пакеты из хранилища и управлять их версиями. Основной pipeline скачивает пакет перед тестированием, а pipeline обновления публикует новую версию. 

npm-пакет с эталонными скриншотами в Azure Artifacts

(npm-пакет с эталонными скриншотами в Azure Artifacts)

У пакета сохраняется история версий. Она позволяет найти предыдущий набор эталонов и использовать его для повторной проверки.

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

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

Есть два механизма хранения.

  • Azure Artifacts хранит версии пакетов, которые используются в разных запусках. В нашем случае это эталонные скриншоты.

  • Артефакты pipeline содержат материалы конкретного запуска: HTML-отчёты, фактические скриншоты, trace-файлы и другие диагностические данные.

история версий npm-пакета с эталонными скриншотами

(история версий npm-пакета с эталонными скриншотами)

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

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

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

7. Настраиваем доступ к пакетам для pipeline и команды

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

В Azure Artifacts права настраиваются для feed – хранилища пакетов, доступного проекту или команде.

Откроем Artifacts → нужный feed → Feed settings → Permissions. Здесь можно назначить роли служебным учётным записям и пользователям.

В список пользователей добавляется учётная запись Build Service, под которой выполняется pipeline. Для обычного запуска screenshot-тестов ей достаточно прав на чтение и скачивание пакета. Чтобы pipeline обновления мог публиковать новую версию эталонов, Build Service выдаётся роль Feed Publisher (Contributor). Она помогает читать пакеты и публиковать новые версии. 

Страница в Azure Artifacts с настройкой ролей и прав для учетных записей

Пользователям доступ к feed выдаётся там же.

Если разработчику или QA нужно только скачать эталоны, ему достаточно роли Feed Reader. Если нужно локально обновлять и публиковать новую версию пакета, требуется Feed Publisher (Contributor). 

Для локальной работы с Azure Artifacts пользователь также создаёт Personal Access Token со scope Packaging Read & Write и использует его для авторизации в npm registry. Важно: сам PAT не выдаёт доступ к feed, у пользователя всё равно должна быть настроена соответствующая роль в его Permissions. 

Карточка выдачи доступа пользователя в feed в Azur Artifacts

То есть у нас доступ разделён просто: pipeline получает права через Build Service, а пользователь – через свою учётную запись и PAT. Для основного pipeline нужно выдать доступ на скачивание эталонов, pipeline обновления, и на публикацию новой версии. А чтобы не копилось много версий, можно указать максимальное количество версий и удалять старые. Для этого в Feed Settings -> Feed Details -> Maximum number of versions per package указать нужное количество.

Карточка с выбором максимального количества версий для хранения эталонов и обновлений

8. Храним секреты и передаём их только нужным шагам

Для запуска автотестов могут понадобиться пароли тестовых пользователей, API-ключи и токены. Если записать их прямо в код или YAML-файл, секреты рискуют попасть в репозиторий и стать доступными посторонним.

В Azure DevOps для таких значений есть secret variables – секретные переменные, а также variable groups - группы переменных, которые можно использовать в нескольких pipeline.

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

Само наличие секрета в Azure DevOps не означает, что любой pipeline сможет его прочитать. Доступ и способ передачи значения нужно настроить явно.

настройки секретной переменной или variable group в Azure DevOps

(настройки секретной переменной или variable group в Azure DevOps)

Для локальной работы с Azure Artifacts PAT хранится в конфигурации авторизации npm registry. Конфигурационный файл с токеном нужно исключить из Git, чтобы он не попал в репозиторий.

После добавления нового секрета стоит проверить всю цепочку:

  1. Значение сохранено в нужной переменной или группе.

  2. Pipeline имеет разрешение использовать эту группу, если оно требуется настройками проекта.

  3. Секрет передан в окружение нужного шага.

  4. Код автотестов читает значение под правильным именем.

  5. Секрет не раскрывается в логах и диагностических отчётах.

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

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

Резюмируем

Azure DevOps позволяет организовать запуск автоматических проверок и работу с их результатами на протяжении всего процесса тестирования.

Решение организовано с помощью инструментов:

  • Azure Pipelines запускает автотесты и отдельные операции.

  • Логи и отчёты помогают понять, какие проверки завершились ошибкой.

  • Артефакты pipeline сохраняют материалы для диагностики конкретного запуска.

  • Test Plans помогает связать автоматизацию с тестовой документацией.

  • Azure Artifacts хранит версии эталонных скриншотов для повторного использования.

  • Настройки доступа и секретные переменные позволяют контролировать работу с пакетами и конфиденциальными данными.

Недавние публикации

Еще по теме

Похожие бизнес-задачи и решения, которые мы нашли, проверили и внедрили