Почему A/B-тесту нельзя доверять: SRM, подглядывание и другие ошибки
Практический чеклист качества A/B-теста: как заметить перекос трафика, подглядывание в результаты, множественные проверки и поломку трекинга.

Иногда A/B-тест заканчивается не выводом, а красивым скриншотом: “победили с +8%”. Но результат мог появиться из-за перекоса распределения, досрочной остановки, нескольких параллельных метрик или сломанного события. Перед тем как поздравлять команду с победой, проверь, не нарушились ли базовые условия эксперимента.
Коротко
Доверие к тесту складывается из трёх вещей: группы получили эксперимент случайно, данные собираются одинаково, а правило остановки было задано заранее. Если хотя бы одно из этих условий нарушено, p-value и uplift создают видимость точности, но не спасают дизайн.
- Проверь SRM: фактическое распределение пользователей между группами должно соответствовать плану.
- Не останавливай тест в тот день, когда случайно появился красивый результат.
- Зафиксируй primary metric, guardrails и срок до старта эксперимента.
- После запуска проверь трекинг и полноту событий до чтения результата.
SRM: группы распределились не так, как планировали
Sample Ratio Mismatch — это ситуация, когда в группах оказалось существенно не то соотношение пользователей, которое задавали в эксперименте. При плане 50/50 ожидаем примерно одинаковое число назначений. Если в control попало 58%, а в test 42%, сначала расследуем рандомизацию, фильтры и доставку варианта, а не обсуждаем uplift.
SRM не доказывает, что результат неправильный, но показывает: механизм эксперимента мог повлиять на то, кто вообще попал в каждую группу. Причина часто находится в SDK, кэше, авторизации, исключении старых пользователей или фильтре уже после назначения варианта.
| Симптом | Куда смотреть |
|---|---|
| Перекос только на одном устройстве | SDK, версия приложения, кэш и повторная инициализация эксперимента |
| Перекос появляется после логина | склейка anonymous_id и user_id, правила исключения и повторное назначение |
| Одна группа теряет пользователей | краш, ошибка загрузки варианта, фильтр доступа или недоставленный feature flag |
| Распределение меняется по дням | сезонность трафика, лимит аудитории и логика ежедневного сэмплирования |
Подглядывание меняет правило игры
Если каждый день смотреть на p-value и останавливать тест при первом значении ниже 0,05, вероятность случайно объявить победителя становится выше заявленных 5%. Это не значит, что нельзя открывать дашборд вообще. Нельзя менять правило решения после того, как увидели промежуточный результат.
Безопасная практика: заранее записать минимальный срок или размер выборки, частоту проверок, primary metric и условие остановки. Если нужен последовательный дизайн, используй его осознанно и с подходящим методом, а не называй обычный тест последовательным задним числом.
Схема иллюстративная: чем чаще команда останавливает обычный тест по промежуточному p-value, тем выше риск ложного сигнала.
Множественные проверки и незапланированные срезы
Тест можно “найти” почти в любом результате, если одновременно проверять десять метрик, пять сегментов и несколько периодов. Один случайный p-value ниже 0,05 среди большого набора проверок не выглядит таким же убедительным, как заранее выбранная основная метрика.
Сегменты нужны для понимания механизма и поиска риска, но не для перебора до первого красивого числа. Отделяй подтверждающий анализ от исследовательского: первый влияет на решение по тесту, второй формирует следующую гипотезу.
- Назови primary metric до запуска и не меняй её на вторую по ходу теста.
- Список guardrail-метрик держи коротким: только реальные риски релиза.
- Сегментные находки помечай как exploratory, если они не были запланированы.
- Для нескольких сравнений используй поправку или отдельный дизайн, а не обычный порог механически.
Проверка событий важнее красивого дашборда
До чтения результата сравни размер аудитории эксперимента с числом пользователей в основной метрике. Если вариант видит 20 тысяч пользователей, а покупка считается только у 11 тысяч из них, нужно понять, это ожидаемый знаменатель или потеря события. Отдельно проверь дубли, задержку загрузки и одинаковую доступность целевого действия в обеих группах.
Полезно иметь диагностический график до primary metric: назначения по дням, доля пользователей с событием, доля неизвестных вариантов, ошибки и время от exposure до целевого действия. Он не заменяет анализ, но быстро показывает, где искать поломку.
| Проверка | Что должно быть понятно |
|---|---|
| Распределение | Фактическое соотношение групп и дата/момент назначения |
| Exposure | Пользователь действительно увидел вариант, а не только был записан в конфигурацию |
| Знаменатель | Одна и та же популяция и правило включения для control и test |
| Событие | Нет систематической потери или дублей целевого события в одной группе |
| Правило решения | Заранее понятно, что делаем при победе, нейтральном результате или guardrail-риске |
Чеклист аналитика
Перед финальным выводом пройди список сверху вниз. Если на каком-то шаге нет ответа, честнее отложить решение и починить эксперимент, чем превращать статистический отчёт в аргумент за уже принятое решение.
- Группы назначаются случайно и сохраняются за пользователем?
- SRM проверен на общей аудитории и ключевых технических срезах?
- Тест прожил заранее заданный срок или достиг плановой выборки?
- Primary metric и guardrails были определены до запуска?
- Данные одинаково полно собираются в обеих группах?
- Сегментные находки отделены от подтверждающего результата?
Материалы по теме
Как тестировать аналитические расчёты на Python и pandas
Практический гайд по тестам для аналитика: проверить метрики на маленьком датасете, поймать регрессию и защитить расчёт от тихих изменений.
Читать материал
Как ускорить pandas: память, типы и обработка больших файлов
Что делать, если pandas медленно работает или не помещает файл в память: категории, downcast, chunksize, Parquet и контроль размера данных.
Читать материал
Pandas apply и векторизация: как писать быстрее и понятнее
Когда использовать apply, почему векторные операции быстрее и как переписать медленный построчный расчёт в pandas.
Читать материал