Привет, Хабр! Меня зовут Вадим Лунин. Я — QA Manager из Альфа Банка в Беларуси.  Поделюсь своим опытом решения одной проблемы, с которой мы столкнулись в связке Allure TestOps + Playwright.  Итак, на одном из проектов мы активно пишем тест‑кейсы в Allure TestOps (на текущий момент их почти 2000) и автоматизируем их, используя Playwright (TypeScript). Около 1400 тест‑кейсов уже удалось автоматизировать. И вот неожиданно мы заметили, что объём наших тест‑кейсов начал увеличиваться в геометрической прогрессии. Проанализировав весь процесс, мы выяснили, что виной всему — генерация дублирующих тест‑кейсов в процессе прогона. Для удобства восприятия и систематизации я разделю свой материал на несколько частей: Инструментарий Как работает Allure TestOps Test case ID History ID Описание проблемы Решение Немного про не пройденные тесты Allure TestOps — это полнофункциональное управление тестированием, ориентированное на автоматизацию в соответствии с DevOps практиками. Playwright (TypeScript) — это библиотека Node.js для автоматизации Chromium, Firefox и WebKit с помощью одного API. allure‑playwright — это подключаемая библиотека для интеграции Allure с Playwright  Чтобы конкретнее описать суть возникшей проблемы, я сначала расскажу как Allure TestOps работает с AllureID. AllureID — это уникальный идентификатор вашего теста в базе данных Allure TestOps. В системе он позволяет соотнести результат с соответствующим тест‑кейсом. Также при привязке Allure ID и HistoryID должно учитываться: fullName — AllureID, HistoryID parameters — AllureID, HistoryID environment — HistoryID Результат теста привязывается к AllureID через testCaseId На основе данных, которые Allure TestOps получает из результата теста, он вычисляет testCaseId. В md5(fullName, sort(names(parameters))) идет завязка на fullName, который отображается в UI. Тест‑кейс считается либо по‑явному указанному ID (AllureID), либо по сигнатуре метода (fullName). Иногда фреймворки сами дают unique test case id, но нужно учитывать, что это бывает не всегда, и это, скорее, исключение из правил. В Allure TestOps это воспринимается как уникальная строка. Мы для этого используем allure‑playwright. Если интеграция до сих пор не отдает testId сама, тогда Allure TestOps сам из fullName вычисляет, что требуется для однозначной идентификации теста. Если тест идет без параметров и мы добавляем новый, то сигнатура метода меняется, и это уже становится другим тест‑кейсом для Allure TestOps. Тот же эффект будет, если изменить имя метода /класса/пакета. Чтобы клеить перезапуски, Allure TestOps нужен hash аргументов, переданных в метод плюс hash значений окружения. Как считается этот hash, не очень важно. Главное, чтобы алгоритм был стабильным. Если от запуска к запуску меняются значения параметров или значения окружения, то это воспринимается как новый результат, а не как перезапуск. В одном spec‑файле мы пишем несколько тестов. В хуке test.beforeEach мы прописываем предусловия (например, авторизация заполнения полей и т. д.), а также аннотации для Allure TestOps. Аннотацию allure.id указываем в каждом тесте. Если тест падает на хуке, то в Allure TestOps создаётся тест по fullName. Таким образом, у нас в системе отображается два теста с одинаковым названием, но разными id. Пример кода как было раньше: После обсуждения этой проблемы с командой — разработчиком Allure TestOps (qameta), и создания тикета — мы нашли решение, которое реализовано в версии 2.3.0 библиотеки allure‑playwright. Для того чтобы избежать дублирования тест‑кейсов, необходимо передавать метаданные в заголовке теста, в нашем случае allure.id. И таким образом, для решения данной проблемы необходимо выполнить две вещи: Обновить allure‑playwright до версии 2.6.0 и выше Указать allure.id в качестве метаданных в заголовке теста, а не аннотации в тесте Здесь cсылка на документацию, где можно ознакомиться, как использовать доступные метаданные в заголовках теста. Вы также можете передать метаданные allure из заголовка теста. Это полезно, когда вам нужно установить allureId для тестов с ошибкой перед хуками. Просто добавьте @allure.id={idValue} для allureId или @allure.label.{labelName}={labelValue} для других типов ярлыков.  Пример кода, как  выглядит тест сейчас: Playwright поддерживает тестовые аннотации для работы с ошибками, ненадежностью, пропусками, фокусировкой и тегами: test.skip() помечает тест как нерелевантный. Playwright не запускает такой тест. Используйте эту аннотацию, если тест неприменим в какой‑либо конфигурации. test.fail() помечает тест как не пройденный. Playwright запустит этот тест и убедится, что он действительно провален. Если тест не провален, Playwright пожалуется. test.fixme() помечает тест как не пройденный. Playwright не будет запускать этот тест, в отличие от аннотации fail. Используйте fixme, когда тест выполняется медленно или с ошибкой. test.slow() помечает тест как медленный и утраивает время ожидания. Аннотации пропуска тестаtest.skip() может быть условным и явным: Исходя из нашего опыта, я бы рекомендовал использовать условный вариант, т. к. при явном использовании всё, что вы будете приписывать в хуках, будет проигнорировано. т. е. если вы задали структуру тестов при помощи аннотаций allure в хуках, то система их пропустит.  QA Manager в Альфа-Банк(Беларусь)