- tests-convention: два кандидата про тесты — один стенд чужого API на пакет, интеграционный тест обязан утверждать - convention-candidates: язык вывода в пяти местах без связывающего правила - quality-review-agents: четыре прохода не сообщили потолок находок — первый замер калибровки
6.1 KiB
🧹 Разобрать кандидатов по тестам и записать конвенцию
- Тип: chore
- Категория: Инфраструктура
- Зачем: как пишем тесты, не записано нигде: пункт «Тесты» в convention-candidates не пересматривали, он обещает фикстуры в testdata/, которых в проекте нет — а трение накопилось (четыре внешних клиента, fakeStore с инъекцией ошибок, env-гейты, флаки-прогон, diff-coverage)
- Теги: sprint:2026-08-06
В docs/conventions/ пять записей, и ни одна не про тесты. Знание о том, как
они здесь устроены, живёт в головах и в самих файлах: фикстуры чужих форматов
константами (testdata не заводился сознательно), интеграционные за env-гейтами
в *_integration_test.go, инъекция ошибок хранилища через fakeStore,
архитектурные правила тестом-сканером internal/archrules с русскими именами,
покрытие изменённых строк меряет гейт.
Пункт «Тесты» в convention-candidates с тех пор не
пересматривали, и он уже расходится с проектом: обещает фикстуры в testdata/,
которого нет и который запрещён CLAUDE.md. Часть остальных кандидатов
проверяется замером, а не мнением: table-driven используется в 18 пакетах из 19,
t.Parallel() — ни разу, testify в go.mod не подключён.
Правило каталога конвенций — «пишем по мере реального трения, а не вперёд».
Трение здесь и есть: тема autotests идёт первым проходом на любой метке ревью,
а дома у неё нет — источником ей служит только семантика гейта из CLAUDE.md,
то есть «что краснеет», а не «что стоит проверять».
Два кандидата пришли из ревью tvdb-title-locale (2026-08-07,
отчёт триажа
→ «Promote candidates»), оба с провенансом прохода, а не из головы:
- один стенд чужого API на пакет. В
tvdb_test.goзавелись два фейка одного и того же API. Когда форма ответа поменяется по факту разведки, забытыйfakeTVDBостанется зелёным и продолжит подтверждать опровергнутое предположение; - интеграционный тест обязан утверждать, а не печатать.
TestIntegration_TVDBпечатает результат и ничего не проверяет:PASSс пустым выводом неотличим от подтверждения. Тест, который нельзя провалить, оракулом не является.
Затрагивает
docs/conventions/tests.md— новый файл записи конвенции;docs/conventions/README.md— строка в индексе «Записи» и, возможно, строки в таблице «Механизировано»;docs/tasks/items/convention-candidates.md— пункт «Тесты» уходит из списка кандидатов;.golangci.ymlиinternal/archrules— только если что-то из решённого выражается правилом, а не прозой.
Критерии приёмки
- Каждый кандидат пункта «Тесты» получил исход поимённо: в прозу, в правило или
выброшен как выдуманный вперёд. Оракул: в
convention-candidates.mdпункта «Тесты» больше нет, а судьба каждого его подпункта названа — в новой конвенции, в таблице «Механизировано» или вREJECTED-строке причины. docs/conventions/tests.mdзаведён и назван в индексе. Оракул:task gate, шагcanon— файл вне канона и битая ссылка краснят безусловно.- Ни одно утверждение конвенции не расходится с тем, как код устроен сегодня:
фикстуры описаны как лежат,
testdataне обещан, число пакетов и приёмов не выдумано. Оракул:grep -r testdataпо репозиторию пуст, и агентdoc-code-driftна ближайшей сессии не даёт находки по этому файлу. - Выражаемое правилом не осталось прозой. Оракул: каждое утверждение новой
конвенции либо отсутствует в таблице «Механизировано», либо стоит там с
адресом механизации — конфигом линтера или тестом
internal/archrules.
Рамки
Существующие тесты под новую конвенцию не переписываются — она применяется к
тому, что пишется дальше. testdata/ не заводится: отказ от него записан в
CLAUDE.md, и его пересмотр — отдельное решение, а не побочный эффект этой
задачи.