сайт в бете
нашли баг? напишите
левин. записаться
весь блог
Тестирование 2026-08-20

Где автотесты сдаются: живой стенд для голосовой комнаты

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

Л
Проект Левин
автор

Голосовая комната в моём форке Buzz — это канал типа voice, который живёт постоянно, как в Discord. Зашёл утром, сидишь фоном, видишь, кто уже сидит. Ветка отдельная, upstream не трогаю. Автоматических проверок в проекте пока ноль: единственный гейт — npm run check, а он смотрит только типы.

Что дала проверка живыми людьми

19 августа мы зашли в комнату вдвоём. Вылезли четыре штуки:

  • я не слышал собеседника;
  • «меня выбило», когда второй зашёл;
  • выйти и зайти помогло;
  • слышно плохо.

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

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

Четвёртый симптом — «слышно плохо» — остался без объяснения. Это отдельная история, и именно она задаёт границу темы.

Где автотест сильнее человека

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

Второй плюс — воспроизводимость редкого. Гонка вылезает при определённом порядке событий. Человек зайдёт десять раз удачно и решит, что всё починено. Тест с подменённым таймером ставит эксперимент ровно в ту точку, где ломается.

Что ещё берут автотесты без вопросов:

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

Раннер я беру встроенный, node:test. Новых зависимостей ради этого добавлять не буду.

Где автотест бессилен

«Слышно плохо». Тут ломается сама идея проверки утверждением. Автотест сравнивает значения. Качество звука — это восприятие. Можно померить jitter, потери пакетов и битрейт, получить зелёные цифры и при этом с трудом разбирать собеседника.

Вещи, которые дают именно такую картину:

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

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

Как я делю

Правило вышло короткое. Симптом сводится к состоянию — это автотест. Симптом сводится к ощущению или к железу — это стенд. Гонка на 250 мс сводится к состоянию: два клиента, один канал, один созвон. Проверяется без человека.

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

Стенд — это дешевле, чем звучит

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

Смысл стенда в том, что он ловит новые формулировки проблем. Автотест ловит уже известные. Каждый раз, когда стенд выдаёт симптом, который сводится к состоянию, он переезжает в node:test и больше человека не отвлекает.

Что дальше

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

Баг #4 нашли люди. Нашли за час и четырьмя разными словами. Тест нашёл бы за секунду и одним.

теги #автотесты#тестирование#голосовая комната#node:test#гонка#webrtc
разберём вашу задачу

Исследовательская сессия автоматизации

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

один разговор — и поймём, чем я могу помочь.

В эпоху ИИ человеку нужен человек. Сяду рядом и доведу до результата — встреча длится столько, сколько нужно. Без скрипта продаж и пакетов «за 999 000 ₽». Если пойму, что помочь не смогу, — скажу сразу.