
Retry в Go автотестах: как перестать бояться flaky-тестов
sound_right 7 минут назад Retry в Go автотестах: как перестать бояться flaky-тестов Средний 5 мин 253 Тестирование IT-систем * Тестирование веб-сервисов * Go * Туториал ВступлениеFlaky-тесты — неизбежная реальность, как...
Anthropic — What company has the best second artificial intelligence model at the end of June?
Вот важная новость с фронта ИИ: sound_right 7 минут назад Retry в Go автотестах: как перестать бояться flaky-тестов Средний 5 мин 253 Тестирование IT-систем * Тестирование веб-сервисов * Go * Туториал ВступлениеFlaky-тесты — неизбежная реальность, как бы нам этого ни хотелось. Особенно в интеграционных и E2E-сценариях, где автотесты зависят от сети, окружения и нестабильных тестовых стендов. Любой временный сбой — и тест падает, а его перезапуск превращается в проблему.
В Go ситуация усугубляется тем, что стандартный пакет testing никак не описывает механизм повторного запуска тестов. В результате команды вынуждены реализовывать retry самостоятельно — и вместе с этим появляются новые ошибки, утечки состояния и непредсказуемое поведение тестов. Сразу важно обозначить: flaky-тесты не стоит лечить ретраями в первую очередь.
Технические детали
В идеале проблема должна решаться на уровне инфраструктуры или тестового сценария. Но если это невозможно и retry всё же необходим — его важно реализовать правильно. В этой статье разберёмся, какие подходы к retry в Go приводят к проблемам и как выглядит корректная модель повторного запуска автотестов.
В качестве примера будем использовать Axiom. Как обычно реализуют retry в GoКогда тесты начинают флапать, первое, что приходит в голову — просто перезапустить тест несколько раз. В Go это обычно выглядит примерно так.
Наивный retryfunc TestSomething(t *testing. T) { for i := 0; i < 3; i++ { err := runTestScenario() if err == } t. Fatal("test failed after retries }На первый взгляд всё выглядит логично: если тест упал из-за временной проблемы, мы просто попробуем ещё раз.
Отраслевые последствия
Но здесь есть фундаментальная проблема — повторяется только функция, а не сам тест. В результате:состояние между попытками не сбрасывается;ресурсы переиспользуются повторно;побочные эффекты накапливаются;поведение теста становится недетерминированным. Фактически это не retry теста, а несколько вызовов одной и той же логики в одном и том же контексте.
Или ещё хужеЧасто следующий шаг — попытка «сделать красиво» через t. Run:func TestSomething(t *testing. T) { for i := 0; i < 3; i++ { t.
Sprintf("attempt-%d", i), func(t *testing. T) { runTestScenario(t) }) } }Здесь кажется, что мы запускаем тест заново. Но на практике это всё тот же один тест с общим состоянием:фикстуры и ресурсы не переинициализируются;контекст и глобальное состояние протекают между попытками;невозможно гарантировать чистый lifecycle;CI начинает вести себя непредсказуемо.
Событие, по словам экспертов, усилит конкуренцию в сфере ИИ.





