Перейти к содержимому

Сгенерированный Xcode проект

Требования
  • Инсайты тестов Xcode настроены (автосгенерированные схемы включают пост-действие tuist inspect test; в пользовательские схемы его нужно добавить).

Нестабильные тесты — это тесты, которые выдают разные результаты (проходят или падают) при многократном запуске с одним и тем же кодом. Они подрывают доверие к вашему набору тестов и отнимают время разработчиков на расследование ложных сбоев. Tuist автоматически обнаруживает нестабильные тесты и помогает отслеживать их со временем.

Страница нестабильных тестов

Как работает обнаружение нестабильности#

Tuist обнаруживает нестабильные тесты двумя способами:

Повторные запуски тестов#

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

Передайте -retry-tests-on-failure или -test-iterations через tuist test:

bash
tuist test --scheme MyScheme -- -retry-tests-on-failure -test-iterations 3

Детали нестабильного тест-кейса

Обнаружение между запусками#

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

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

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

Управление нестабильными тестами#

Автоматическая очистка#

Обнаружение и очистка выполняются через автоматизацию оповещений в проекте. Каждый проект получает автоматизацию «Обнаружение нестабильных тестов» по умолчанию, чей триггер помечает тест как нестабильный, а восстановление снимает флаг, когда тест проходит настроенное окно восстановления (по умолчанию 14 дней) без повторного срабатывания. Отредактируйте её в разделе Настройки → Автоматизации, чтобы изменить окно восстановления, заменить действия восстановления (например, также снять карантин) или полностью отключить восстановление, чтобы тесты оставались помеченными как нестабильные, пока вы не очистите их вручную.

Ручное управление#

Вы также можете вручную помечать или снимать пометку нестабильности с тестов на странице деталей тест-кейса. Это полезно, когда:

  • Вы хотите подтвердить известный нестабильный тест во время работы над исправлением
  • Тест был ошибочно помечен из-за проблем с инфраструктурой

Карантин нестабильных тестов#

Карантин изолирует нестабильный тест, чтобы он не блокировал CI, пока вы его исправляете. По умолчанию это ручное действие — вы помещаете в карантин, снимаете с карантина и переключаете режимы на странице деталей тест-кейса в дашборде — но вы также можете настроить это через автоматизацию оповещений в разделе Настройки → Автоматизации, чтобы тест автоматически заглушался (или пропускался) при превышении порога нестабильности и снимался с карантина при восстановлении. Каждый переход, ручной или автоматический, записывается в журнал аудита тест-кейса.

Тест в карантине находится в одном из двух режимов:

  • Заглушен: тест всё ещё запускается, но tuist test маскирует сбой. Сбои всё ещё поступают в детектор нестабильных тестов, поэтому вы можете продолжать наблюдать за тестом, не ломая сборку. Выберите этот режим для теста, который вы активно исследуете.
  • Пропущен: xcodebuild получает -skip-testing <identifier>, поэтому тест никогда не запускается. Он не производит новых результатов и исчезает из дашборда нестабильных тестов, пока вы не включите его снова. Выберите этот режим, когда тест сломан, медленный или настолько постоянно нестабилен, что его запуск просто тратит минуты CI впустую.

Почему тесты в карантине могут отображаться как прошедшие#

  • Заглушенные тесты всё ещё выполняются. Заглушенный тест, который падает, записывается как упавший в запуске тест-кейса и помечается как нестабильный — статус отдельного теста не перезаписывается. Переопределяется общий результат запуска теста: если каждый падающий тест-кейс в запуске заглушен, весь запуск сообщается как пройденный, поэтому заглушенные сбои не ломают CI.
  • Пропущенные тесты вообще не запускаются, поэтому дашборд продолжает показывать статус последнего фактического выполнения теста — этот снимок может быть недельной давности.

Запуск тестов#

tuist test автоматически учитывает оба режима:

bash
tuist test

Пропущенные тесты передаются в xcodebuild как -skip-testing и никогда не запускаются. Заглушенные тесты запускаются нормально; если они падают, сбой маскируется в результирующем статусе сборки.

Чтобы полностью обойти карантин и запустить всё, включая заглушенные и пропущенные тесты:

bash
tuist test --skip-quarantine

Стресс-тестирование новых тестов#

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

Тест-кейс считается новым, если он не запускался в CI за последние 90 дней на основной ветке проекта или на коммите, который впоследствии попал в неё. При наличии очереди слияния тест-кейс, запущенный очередью, становится известным, когда коммит очереди попадает в ветку, и остаётся новым, если очередь его сбрасывает. Коммиты сопоставляются через историю Git, которую Tuist собирает в CI.

Включение#

Гейт по умолчанию отключен. Установите режим:

  • report: предупреждает о каждом нестабильном тест-кейсе. Запуск всё ещё завершается со своим собственным результатом.
  • enforce: нестабильный тест-кейс приводит к провалу запуска с тем же кодом выхода, что и упавший тест.

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

Начните с report на пару недель, чтобы увидеть, что бы заблокировал enforce.

Передайте его перед аргументами сквозной передачи или установите TUIST_TEST_STRESS_NEW_TESTS, чтобы менять режим для каждого канала CI:

bash
tuist test --stress-new-tests report

Сколько раз каждый тест перезапускается#

Это зависит от того, сколько времени занял тест-кейс при первом проходе:

Первый проходПовторные запуски
До 5 с10
До 10 с5
До 30 с3
До 5 мин2
Более 5 минНе перезапускается

Повторные запуски используют результаты сборки первого прохода. Проход останавливается после 200 тест-кейсов или 10 минут — в зависимости от того, что наступит раньше, и сообщает, какой лимит был достигнут.

Когда гейт не запускается#

  • Первый проход уже завершился неудачей. Сначала исправьте эти тесты.
  • У проекта нет основной ветки, или в ней еще ничего не запускалось в CI.
  • Более 30% тест-кейсов проекта выглядят как новые. Повторный запуск такого количества займет больше времени, чем это оправдано. Этого стоит ожидать в проекте, который только начал отправлять отчеты в Tuist, или после переименования, которое перемещает много тестов сразу.

Уведомления в Slack#

Получайте мгновенные уведомления, когда тест становится нестабильным, настроив оповещения о нестабильных тестах в вашей интеграции со Slack.

Запрос состояния нестабильности и карантина#

CLI#

Дерево команд tuist test case предоставляет всю информацию, которую Tuist отслеживает о тест-кейсе:

bash
tuist test case list --flaky # only flaky test cases
tuist test case list --quarantined # only muted or skipped test cases
tuist test case show <test_case_id> # detail: flakiness rate, last status, run counts
tuist test case events <test_case_id> # audit log: marked_flaky, muted, skipped, ...
tuist test case run list <test_case_id> # run history with status and duration
tuist test case run show <test_case_run_id> # single run, including failure breakdown

Все они принимают --json для скриптинга.

REST API#

Те же данные доступны по HTTP — см. эндпоинты тест-кейсов в справочнике API для полного списка маршрутов, фильтров и полей ответа. Чтобы изменить состояние тест-кейса (пометить или снять пометку нестабильности, заглушить, пропустить), отправьте PATCH /api/projects/{account_handle}/{project_handle}/tests/test-cases/{test_case_id} с is_flaky или state. То же изменение доступно через tuist test case update и как инструмент Model Context Protocol update_test_case.