Слогер Создать блог
Разработка

Как выбрать, какой flaky-тест чинить первым: метрика и практика

Когда в проекте три десятка ненадёжных тестов, главный вопрос — не «флакает ли тест», а «какой из них чинить в ближайший четверг». Обычный процент падений тут не поможет: он не отличает сломанный тест от периодически сбоящего и ничего не говорит о цене каждого флака. Разбираем метрику, которая всё это учитывает.

Когда у вас тридцать нестабильных тестов, вопрос «флакает ли этот тест» перестаёт быть вопросом. Вы и так знаете, что флакает. Вопрос в другом: какой из них чинить в четверг днём, когда есть два часа и куча других задач. Для этого нужен балл, который ранжирует тесты по реальной важности. Самая очевидная метрика — число падений на сотню запусков — с этой задачей справляется плохо. И вот почему.

Почему «падения на сотню запусков» — плохой ответ

У наивной метрики два недостатка. Первый бросается в глаза: тест, который просто сломан, падает в ста запусках из ста и возглавляет список. Но это не флаки, это регрессия, и чинится она совсем иначе. Любая метрика, которая не отличает эти случаи, заставит вас потратить четверг не на то.

Второй недостаток тоньше. Метрика считает только долю падений и выбрасывает порядок наблюдений. Тест, который упал десять раз во вторник и с тех пор зелёный, приравнивается к тесту, который падает дважды в неделю стабильно. Это разные ситуации с разными действиями: первый — уже разрешённый инцидент, второй — постоянный налог. Хорошая метрика должна их различать.

Обе проблемы лечатся одним способом: перестать игнорировать порядок исходов.

Flip rate: что это и зачем

Упорядочим запуски одного теста по времени и посмотрим на последовательность результатов. Возьмём два теста с одинаковой долей падений:

ПоказательТест AТест B
Доля падений0.500.50
Число переходов (flips)113
Flip rate1/19 = 0.0513/19 = 0.68

Тест A — это не флаки. Он сломался в конкретный момент и с тех пор падает всегда: классическая регрессия, находится бисекцией, у неё есть первый плохой коммит. Тест B — по-настоящему нестабилен. Доля падений тут бессильна, flip rate разделяет их полностью.

Считается просто:

flip_rate = количество переходов / (запуски - 1)

Переход — это позиция, где результат в запуске i отличается от результата в запуске i-1. Запуски упорядочены по времени коммита.

У flip rate есть естественный потолок. Идеально чередующаяся последовательность даёт 1.0. Тест, который ведёт себя как подбрасывание монетки с 50% падений, в среднем покажет около 0.5. Если значение приближается к единице, это не случайный шум, а что-то, что систематически переключается: зависимость от порядка тестов, общий ресурс, который кто-то переключает, два узла деплоя с разными версиями модели. Это другой баг и другое исправление, и метрика сразу указывает на него.

Проблема малых выборок

Тест с четырьмя запусками и одним флаком имеет точечную оценку 25%. Тест с четырьмястами запусками и сорока флаками — 10%. Если ранжировать по сырой доле, первый окажется выше второго. Это неправильно: про первый тест вы почти ничего не знаете, про второй — очень много. Нужно ранжировать по нижней границе доверительного интервала, а не по оценке.

Обычный выбор — нижняя граница интервала Уилсона. Она ведёт себя разумно, когда число падений равно нулю или доля близка к границе, где нормальное приближение врёт. Код:

from math import sqrt def wilson_lower_bound(successes, n, z=1.96): """Нижняя граница интервала Уилсона.""" if n == 0: return 0.0 phat = successes / n denom = 1 + z * z / n centre = phat + z * z / (2 * n) margin = z * sqrt((phat * (1 - phat) + z * z / (4 * n)) / n) return (centre - margin) / denom wilson_lower_bound(1, 4) # тест из 4 запусков, 1 флак wilson_lower_bound(40, 400) # тест из 400 запусков, 40 флаков

Эффект: чтобы тест поднялся в списке, нужны доказательства. Один флак из четырёх запусков опускается вниз, пока не накопит достаточно истории. Умеренная, но стабильная доля на сотнях запусков поднимается выше. Это та же поправка, что используется при ранжировании долей где угодно, и именно она превращает список новичков в список реальных проблем.

Применяйте нижнюю границу к flip rate, а не к доле падений — ведь ранжировать хотите именно по ней. Учтите: знаменатель на единицу меньше числа запусков, это заметно только для очень малых выборок, а их эта граница как раз и призвана понижать, так что приближение безвредно. Выберите один z и не меняйте его: смена z между отчётами перетасует рейтинг по причинам, не связанным с тестами.

Ранжирование по ущербу, а не по доле

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

score = wilson_lower_bound(flaky_runs, total_runs) * runs_per_week * blast_radius blast_radius: 4 — блокирует мердж в основной ветке 2 — блокирует мердж в фиче-ветке 1 — ночной прогон, никого не блокирует

Теперь у единиц есть смысл: «ожидаемые заблокированные мерджи в неделю». Тест с 30% флаков, который запускается раз ночью, опустится ниже теста с 3% флаков, который запускается на каждый пуш в оживлённый репозиторий. Это правильный порядок, и сортировка по доле его не даст.

Уровни blast radius намеренно грубые. Трёх достаточно, чтобы расставить порядок, и их мало, чтобы никто не спорил полдня, заслуживает ли тест двойку с половиной. Не добавляйте слагаемое за важность фичи: каждый считает свою фичу самой важной, и итоговый балл перестанет быть сравнимым между командами. Эта метрика измеряет стоимость флака, а не ценность фичи.

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

Как эту метрику используют неправильно

  • Как целевой показатель. Если инженеров оценивают по этому баллу, они будут снижать его удалением тестов. Используйте его для ранжирования, но не отчитывайтесь по нему как по метрике команды.
  • Сравнение несовместимых окон. Нельзя сравнивать тест, живущий год, с тестом, добавленным во вторник. Для обоих нужно одинаковое окно, иначе доверительная граница считает разные вещи.
  • Без исключения известных инцидентов. Четырёхчасовой сбой провайдера перевернёт все тесты в наборе и перемешает весь рейтинг. Помечайте такие запуски по сигнатуре и исключайте: сбой — не свойство теста.
  • В наборе без ретраев. Если на каждый запуск только одна попытка, флак и полноценное падение — одно и то же событие. Вся метрика схлопывается в долю падений со всеми исходными проблемами.

Вывод

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

По материалам: ai. Текст переработан редакцией Слогера.

← На главную

Рекламное место — Конец поста
Реклама · Слогер

Комментарии (0)

Войдите, чтобы комментировать.

Пока нет комментариев. Будьте первым.

Карьера

Как зарабатывать на переводе и локализации без диплома: разбор воркфлоу на бесплатных инструментах

Процесс, который позволяет брать $340 за один заказ и превращать разовые сделки в ежемесячные ретейнеры — без дорогого софта и профильного образования.

Слогер 28.09.2026 ▲ 0
Образование

Как проверить старые соцсети перед визой и учёбой за рубежом: 6 категорий и порядок действий

Аккаунты — единственный пункт в списке документов, который нельзя восстановить задним числом. Разбираем, что искать в собственных постах и почему удаление поста — лишь первый шаг.

Слогер 28.09.2026 ▲ 0
Карьера

Чистка цифрового следа перед собеседованием: график на 6 недель и что уже поздно начинать

Рекрутеры чаще гуглят кандидата не на этапе отклика, а когда он уже в шортлисте. Отсюда и запас времени, и жёсткий дедлайн — разбираем обратный отсчёт по неделям.

Слогер 28.09.2026 ▲ 0
Образование

Как учиться сложным вещам: система, где знания проверяются действием, а не перечитыванием

Пять приёмов из практики преподавания и self-learning в кибербезопасности: карта вместо первой страницы, worked examples, извлечение из памяти, интервалы и цикл «сломал — починил — объяснил».

Слогер 28.09.2026 ▲ 0
Fluxs lenta
Реклама · fluxs.ru
Карьера

Как подготовиться к собеседованию по кодингу: 7 книг и порядок, в котором их читать

Провал на интервью редко связан с тем, что вы не умеете программировать. Чаще не хватает системы, словаря для разговора о дизайне и практики объяснять решение вслух — и всё это можно закрыть книгами.

Слогер 27.09.2026 ▲ 0
Карьера

Как откликаться на вакансии без диплома: разбор фильтра, который отсеивает за две минуты

Junior-вакансия с Python, SQL и автоматизацией, три документа от кандидата — и отказ через 120 секунд после отправки. Разбираем, что здесь происходит и как проходить такие воронки, если диплома нет.

Слогер 27.09.2026 ▲ 0
Fluxs lenta
Реклама · fluxs.ru
Карьера

Почему резюме не работает: как доказать навыки живыми проектами

Разбор подхода proof-of-work: зачем показывать работающий продукт и видео-демо вместо строчки «разрабатывал сервис», как это обходит автоматические фильтры и что подготовить, чтобы запрос на интервью не ушёл в пустоту.

Слогер 26.09.2026 ▲ 0
Fluxs lenta
Реклама · fluxs.ru
Стартапы

Конструктор бизнес-модели: схема из рабочих модулей, которую можно перенести на Fluxs

Это не просто схема. Каждый блок в нашем конструкторе бизнес-модели настоящий работающий модуль Fluxs: воронка, лиды, письма, мессенджер, 1С, поставка. Поэтому нарисованное можно перенести на платформу: по выбранным блокам подключаем и настраиваем те же модули, вы делаете это сами или с нами. Подходит и новому делу, где нужно понять, что вообще понадобится, и действующему бизнесу: увидите, каких сценариев не хватает, достроите их и переложите работу на Fluxs по частям, без остановки.

Слогер 25.09.2026 ▲ 0