В CI отдельный тест может зависнуть без завершения и блокировать job. Какой механизм должен ограничивать длительность его выполнения?
Используйте тайм-аут выполнения теста с принудительной отменой по истечении заданного времени. Обычно задают ограничения на уровне отдельного теста или набора, а тайм-аут CI-job оставляют как последний рубеж.
Тайм-аут должен завершать зависший процесс, фиксировать тест как неуспешный и сохранять диагностические материалы. Он не устраняет первопричину зависания, поэтому повторные запуски сами по себе проблему не решают.
Автоматические тесты запускаются в ограниченных ресурсах CI: зависший процесс занимает исполнитель, блокирует последующие этапы и может удерживать внешние ресурсы. Поэтому в инструментах автоматизации и CI появились ограничения времени как механизм защиты от бесконечного ожидания.
Изначально такой контроль был особенно важен для UI-тестов, сетевых взаимодействий и интеграционных проверок, где отсутствие ответа не всегда приводит к немедленной ошибке. Тайм-аут превращает неопределённое ожидание в наблюдаемое событие с конечным результатом.
Без тайм-аута тест, ожидающий ответ сервиса, освобождение ресурса или завершение фоновой операции, может работать бесконечно. В результате CI-job не завершается, исполнитель становится недоступен, а команда не получает своевременную обратную связь.
Слишком большой тайм-аут маскирует зависания и замедляет диагностику. Слишком маленький создаёт ложные падения на медленных, но исправных окружениях. Дополнительный риск возникает при принудительном завершении: незавершённая очистка может оставить данные, процессы или блокировки.
На уровне тестового фреймворка задают тайм-аут теста — максимальную длительность его выполнения. По истечении срока раннер должен отменить тест, пометить его как неуспешный и собрать доступные логи, снимок состояния, трассировку или другие артефакты.
Полезно разделять уровни ограничений:
Значение следует выбирать по измеренным временам выполнения, а не по максимальному терпимому ожиданию. Часто ориентируются на нормальное время операции с запасом на вариативность CI, затем анализируют превышения и корректируют границы.
Отмена должна быть корректной настолько, насколько это позволяет используемый раннер: сначала сигнал завершения и выполнение очистки, затем принудительное завершение оставшегося процесса. Фикстуры и внешние ресурсы должны иметь собственные ограничения и гарантированное освобождение, но нельзя рассчитывать, что очистка всегда успеет выполниться после жёсткого убийства процесса.
Тайм-аут не следует автоматически сочетать с бесконтрольным повтором. Повтор может временно скрыть зависание, увеличить нагрузку и оставить побочные эффекты. Если зависания повторяются, нужно исследовать блокировки, утечки ресурсов, отсутствие тайм-аутов у сетевых клиентов, проблемы синхронизации и состояние окружения.
Интеграционный тест периодически ждёт сообщение от брокера, но при нарушении маршрутизации не получает его никогда. В CI job остаётся активной часами, пока не сработает общее ограничение платформы.
Рассматривались три варианта. Уменьшить только общий тайм-аут job было быстро, но это не показывало, какой тест завис, и задерживало обратную связь. Добавить повторы было неуместно: повтор не исправляет отсутствие сообщения и создаёт дополнительную нагрузку. Оставить ожидание без ограничения означало сохранять риск блокировки исполнителя.
Выбрали тайм-аут на ожидание сообщения и отдельный тайм-аут теста, а при превышении сохраняли логи брокера и состояние потребителя. Общий тайм-аут job оставили как аварийный предел. В результате зависший сценарий стал быстро завершаться с понятным диагнозом, а проблема маршрутизации перестала блокировать весь CI.
Тайм-аут операции ограничивает конкретное ожидание: запрос, чтение сообщения или готовность элемента. Тайм-аут теста защищает весь сценарий, включая подготовку, несколько операций и очистку. Нужны оба уровня: операция должна завершаться предсказуемо, а тест — иметь общий верхний предел на случай зависания вне этой операции.
Нет. Общий тайм-аут защищает ресурсы CI, но плохо локализует причину: он может прервать job с несколькими тестами или зависшей фикстурой. Такой предел необходим как последний рубеж, однако диагностические тайм-ауты следует задавать ближе к месту ожидания и на уровне теста.
Нужно убедиться, что отмена не оставляет процессы, временные файлы, блокировки, записи в базе или сообщения, которые повлияют на следующие тесты. Следует сохранять диагностические артефакты до уничтожения окружения и проверять, выполняется ли очистка при обычной отмене. Если после жёсткого завершения очистка ненадёжна, безопаснее запускать тесты в изолированном окружении, которое можно целиком удалить и создать заново.