Перейти к содержимому
15 / 15

Тестирование конкурентного кода на Go: детерминизм и нестабильные тесты

Конкурентный тест плох тем, что его результат зависит от планировщика. Три приёма делают его надёжным. Первый — обязательный -race в CI: без него гонки просто не проверяются. Второй — отказ от time.Sleep как средства синхронизации: пауза не гарантирует ничего и превращает тест в лотерею, вместо неё синхронизируются каналами или WaitGroup. Третий и самый мощный появился в стандартной библиотеке — пакет testing/synctest: synctest.Test запускает код в изолированном «пузыре», где время фальшивое и управляется рантаймом. Внутри пузыря time.Sleep(time.Hour) возвращается мгновенно, как только все горутины пузыря заблокированы, — то есть тест с таймаутами и тикерами становится детерминированным и быстрым, без замены часов на интерфейс. Дополнительно -count помогает выловить редкие гонки повторами, а t.Parallel с t.Cleanup держит тесты изолированными. Утечки горутин проверяют сравнением их числа до и после.

Тестирование конкурентного кода на Go: детерминизм и нестабильные тесты | JScriptiser