Документация Синхронизация обнаружения тестов

Синхронизация обнаружения тестов

Об URL в примерах: во всех примерах используется адрес 127.0.0.1:5770 по умолчанию. Если ваш экземпляр работает на удалённом сервере, замените его на фактический адрес. Подробнее — Полезные функции и советы.

Синхронизация обнаружения тестов регистрирует весь инвентарь ваших тестов
в каталоге TCM прямо из CI — включая тесты, которые в текущей сборке не
запускались. Вы загружаете небольшой JSON-манифест со списком всех тестов,
которые собрал ваш фреймворк, а Mockarty сверяет его с тест-кейсами
пространства имён: новые тесты создаются, существующие сохраняют свои
человекоориентированные метаданные, а тесты, исчезнувшие из кода, могут быть
помечены как осиротевшие (orphaned).

Это дополняет внешние прогоны: внешний прогон сообщает
Mockarty о тесте только в момент его выполнения. Синхронизация обнаружения
поддерживает каталог живым зеркалом кодовой базы, поэтому тест, который вы
пропустили или поместили в карантин в этой сборке, всё равно виден в TCM.

Что она делает

Итог Значение
created Для теста из манифеста ещё не было соответствующего кейса — создан новый кейс.
updated Для теста из манифеста кейс уже существовал — обновлены отметка об обнаружении и (для авто-обнаруженных) имя; ваши ручные правки сохранены.
orphaned Только при pruneMissing: true: кейс, ранее обнаруженный под этим source, отсутствует в текущем манифесте, поэтому помечен как осиротевший. Осиротевшие кейсы никогда не удаляются — они остаются для просмотра и экспорта.
total Число уникальных тестов в манифесте.

Каждый обнаруженный тест сопоставляется по детерминированной идентичности. Если
вы задали явный testCaseId, он становится авторитетным ключом (он переживает
переименование метода или параметров); иначе используется обязательный
fullName. Это тот же ключ, по которому сопоставляется внешний прогон, поэтому
тест, обнаруженный здесь и позже выполненный, попадает в один и тот же кейс.

Формат манифеста

{
  "source": "pytest:auth-suite",
  "framework": "pytest",
  "pruneMissing": true,
  "cases": [
    {
      "testCaseId": "AUTH-1042",
      "fullName": "tests.auth.test_login.test_valid_credentials",
      "name": "Вход с корректными учётными данными",
      "suite": "tests.auth.test_login",
      "description": "Пользователь может войти с верным email и паролем.",
      "sourceRef": "tests/auth/test_login.py:42",
      "labels": ["auth", "smoke"]
    },
    {
      "fullName": "tests.auth.test_login.test_locked_account",
      "name": "Заблокированная учётная запись отклоняется",
      "sourceRef": "tests/auth/test_login.py:58"
    }
  ]
}
Поле Обязательно Примечания
source да Ключ области для этого манифеста (например, pytest:auth-suite). Удаление лишних кейсов ограничено одним source, поэтому манифест одного набора никогда не осиротит кейсы другого.
framework нет Информационное (например, pytest, go, junit).
pruneMissing нет При true кейсы, обнаруженные под этим source, но отсутствующие в cases, помечаются осиротевшими. При false (по умолчанию) синхронизация только добавляет.
cases[].fullName да Детерминированная идентичность теста. По ней тест сопоставляется между синхронизациями и с результатами прогонов.
cases[].testCaseId нет Явная закреплённая автором идентичность (например, @allure.id). При наличии — авторитетный ключ сопоставления.
cases[].name нет Отображаемое имя. По умолчанию равно fullName. Имя переносится на авто-обнаруженные кейсы при каждой синхронизации; ручные кейсы не затрагиваются.
cases[].description нет Свободный текст. Устанавливается только при создании кейса, чтобы ваши ручные правки переживали повторные синхронизации.
cases[].sourceRef нет Где тест находится в коде (file:line или URL репозитория), для «перейти к исходнику».
cases[].labels нет Становятся тегами кейса при создании.
cases[].suite нет Необязательная подсказка группировки; зарезервировано для будущего размещения по папкам.

Синхронизация через API

POST /api/v1/namespaces/{namespace}/tcm/discovery

curl -X POST http://127.0.0.1:5770/api/v1/namespaces/default/tcm/discovery \
  -H "Authorization: Bearer $MOCKARTY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d @manifest.json

Ответ:

{
  "source": "pytest:auth-suite",
  "created": 2,
  "updated": 18,
  "orphaned": 1,
  "total": 20
}

Аутентификация и права. Передавайте токен API как
Authorization: Bearer <token>. Эндпойнт требует право test_case:write
(манифест — это запись в рабочее пространство) и функцию TCM.

Синхронизация через CLI

CLI оборачивает эндпойнт командой mockarty-cli tcm discover. Манифест читается
из файла (--manifest <path>) или из stdin (--manifest -).

# Из файла, с областью и удалением лишних кейсов этого source:
mockarty-cli tcm discover --manifest cases.json --source pytest:auth-suite --prune

# Из stdin, в конвейере CI:
pytest --collect-only -q | my-converter | \
  mockarty-cli tcm discover --manifest - --source pytest:auth-suite --framework pytest --prune
Флаг Назначение
--manifest Путь к JSON-манифесту или - для stdin. Обязательно.
--source Переопределяет верхнеуровневый source манифеста (ключ области для удаления лишних).
--framework Переопределяет верхнеуровневый framework манифеста.
--prune Помечает осиротевшими кейсы, отсутствующие в манифесте (под тем же source).

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

Семантика осиротения (pruneMissing)

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

  • Без pruneMissing (или --prune) синхронизация только добавляет и
    обновляет — ничего не осиротеет.
  • С ним Mockarty сравнивает кейсы, ранее обнаруженные под этим source, с
    текущим манифестом. Исчезнувшие помечаются осиротевшими — это мягкое
    состояние, а не удаление. Они остаются видимыми и экспортируемыми, чтобы QA
    решил, был ли тест удалён намеренно.
  • Поскольку удаление лишних ограничено одним source, запуск манифеста
    auth-suite никогда не затрагивает кейсы, обнаруженные манифестом
    checkout-suite.

Повторная синхронизация неизменного манифеста идемпотентна: ничего нового не
создаётся и ничего лишнего не осиротеет.

Ограничение частоты (HTTP 429)

Манифест может содержать тысячи кейсов, каждый — это upsert. Чтобы защитить базу
данных, когда большой парк CI синхронизируется одновременно, сервер ограничивает
число одновременно выполняемых синхронизаций. При достижении предела эндпойнт
возвращает HTTP 429 с заголовком Retry-After: 1:

HTTP/1.1 429 Too Many Requests
Retry-After: 1

Сделайте паузу и повторите. CLI и SDK повторяют 429 с экспоненциальной задержкой
автоматически. Предел параллелизма по умолчанию равен учетверённому числу
процессоров сервера и настраивается администратором переменной окружения
MOCKARTY_DISCOVERY_CONCURRENCY (диапазон 2–1024).

Уведомления

Когда синхронизация действительно меняет каталог — созданы новые кейсы и/или
кейсы осиротели — Mockarty отправляет событие discovery synced в настроенные
вебхуки и каналы уведомлений пространства имён, а также шлёт живое обновление в
любое открытое дерево кейсов, чтобы новые/осиротевшие кейсы появились без ручного
обновления. Холостая повторная синхронизация (всё updated, ничего нового и
осиротевшего) остаётся «тихой», чтобы прогоны CI не засыпали подписчиков.

См. также