Unit tests — что и как покрывать
Статья для людей. Для агентов и IDE: skill introvert-testing и файл coverage.md в той же папке skill.
Принцип
Каждый тест должен отвечать на вопрос: какую регрессию он поймает?
Не пишем тесты «на каждый новый метод» и не проверяем, что stub вернул захардкоженную строку.
Когда тест нужен
| Слой | Примеры |
|---|---|
| Domain / чистая логика | парсинг, фильтры, границы, state machine |
| Remote repository | маппинг ошибок (401, timeout), DTO → entity, cache fallback |
| Converter | null, unknown enum, вложенные поля |
| Provider | только если есть логика поверх вызова репозитория |
| Drift | миграции, нетривиальные DAO-запросы |
| UI | golden в Sandbox или Marionette smoke |
Когда тест не нужен
- Stub/fake просто возвращает константу
- Provider — одна строка
repo.call().toValue() - Сгенерированный код (Freezed, routes, Pigeon, Drift)
- «Метод вернул ok» без проверки смысла
Стиль в репозитории
- Assertions:
package:checks/checks.dart - Имена тестов — по поведению:
maps 401 to NotAuthenticatedFailure - Образцы:
features/banners/test/home_banners_test.dart,features/core/test/iterable/range_test.dart
Запуск
bash
melos test
fvm flutter test path/to/single_test.dartПодробные сценарии и антипаттерны — в .cursor/skills/introvert-testing/coverage.md.