Golang Дайджест
8.1K subscribers
36 photos
1 file
179 links
Самое интересное из мира Go: новости, статьи, проекты, сервисы, изменения в языке и др.

Посты публикуются не часто - только самое важное, с чем я лично ознакомился.

Поэтому можно не мьютить канал =)

Обратная связь: @justskiv
Download Telegram
Testing Time: тестируем асинхронный код без time.Sleep в Go 1.25

Пост про testing/synctest в официальном блоге разработчиков Go

- Оригинал
- Хороший перевод

Go Team наконец-то решили давнюю проблему тестирования конкурентного кода. В 1.24 вышел экспериментальный пакет testing/synctest, а в 1.25 он стал стабильным.

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

Проблема стара как мир:

- Тестируешь context.WithDeadline — либо ждёшь реальную секунду (медленно), либо не ждёшь достаточно (тест нестабилен, флапает)

- Добавляешь time.Sleep с запасом — тест тормозит

- Убираешь запас — тест падает на CI под нагрузкой

Классический выбор: slow or flaky, pick... one!

Решение — пузырь с двумя функциями:

- synctest.Test(t, func(t *testing.T) {...}) — запускает функцию в пузыре с фейковым временем

- synctest.Wait() — ждёт, пока все горутины в пузыре станут "durably blocked"

- Время идёт только когда все заблокированы, вычисления занимают 0 времени

- Начало эпохи: полночь 1 января 2000 UTC (как в Go Playground)

Пример до/после:
// Было: медленно и ненадёжно
time.Sleep(time.Until(deadline) + 100*time.Millisecond)

// Стало: быстро и стабильно
synctest.Test(t, func(t *testing.T) {
time.Sleep(time.Until(deadline))
synctest.Wait()
})


————

Мне понравилось, что автор также рассказывает про историю создания. Сначала пытались добавить поддержку тестирования прямо в http-пакет — не вышло, особенно с HTTP/2. Потом сделали грязный хак с парсингом runtime.Stack() — работало, но стыдно показать. В итоге добавили поддержку прямо в рантайм.

Из ограничений: не работает с реальной сетью (вместо этого нужно использовать их имитацию в памяти — in-memory fake), мьютексы не считаются durably blocking, syscalls и cgo тоже. Но для 95% кейсов — самое то.

Забавно, что самый первый пример в статье — тест для context.WithDeadline. Видимо, это была та самая боль, с которой всё началось 🙃

#go1_25 #go_official #testing #concurrency
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍5🔥5
🧪 Сравнение инструментов для генерации моков

https://habr.com/ru/companies/avito/articles/939388/

Семён Эйгин из Авито (мейнтейнер minimock) сравнивает три популярных инструмента для генерации моков:

- mockery
- gomock
- minimock

Очевидно, автор предвзят, но статья всё равно интересная. Просто учитывайте это во время чтения.

Какие проблемы обсуждаются:

1. Типизация параметров

- mockery и gomock используют interface{} в ожиданиях: GetUser(1) интерпретируется как int вместо int64
- minimock генерирует строго типизированные методы: Expect(id int64)
- На практике: можно пропустить ошибку в стиле (int64=1) != (int=1)

2. Контроль количества вызовов

- gomock по умолчанию разрешает только один вызов метода
- mockery и minimock позволяют неограниченные вызовы
- Двойственная ситуация: gomock помогает поймать лишние вызовы, но требует явного Times() или AnyTimes()

3. Тестирование асинхронного кода

- mockery: приходится встраивать каналы через RunAndReturn — плохо масштабируется
- gomock: нужен самописный хелпер с controller.Satisfied()
- minimock: встроенная поддержка через mc.Wait(timeout)

————

Выбор автора, предсказуемо — minimock как "самый простой и топорный, покрывающий 99% случаев".

И я в целом согласен: строгая типизация экономит время на дебаге, встроенная поддержка асинхронности избавляет от костылей.

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

#article #testing #mocks
50👍10🤔2