2 KiB
2 KiB
Testing — Conventions & Patterns
Structure
Test files mirror lib/ under test/:
test/
features/
timer/
timer_repository_test.dart
timer_notifier_test.dart
entries/
entries_repository_test.dart
projects/
projects_repository_test.dart
reports/
reports_repository_test.dart
core/
database/
app_database_test.dart
What to Test
| Layer | Test type | Tool |
|---|---|---|
| Repository | Unit | mocktail + drift in-memory |
| Notifier | Unit | ProviderContainer |
| Screen | Widget | flutter_test |
| Navigation | Widget | GoRouter test helpers |
Repository Tests — Pattern
Use an in-memory Drift database:
AppDatabase createTestDb() => AppDatabase(NativeDatabase.memory());
Test every public DAO method: insert, update, delete, watch (stream).
Notifier Tests — Pattern
Use ProviderContainer with overridden repository:
final container = ProviderContainer(overrides: [
projectsRepositoryProvider.overrideWithValue(MockProjectsRepository()),
]);
addTearDown(container.dispose);
Widget Tests — Pattern
await tester.pumpWidget(
ProviderScope(
overrides: [/* mock providers */],
child: const MaterialApp(home: TimerScreen()),
),
);
- Verify key widgets are present
- Tap interactions and verify state changes
- Use
mocktailwhen()/verify()for interactions
Mocktail Conventions
class MockTimerRepository extends Mock implements TimerRepository {}
// Setup
when(() => mock.getActiveEntry()).thenAnswer((_) async => null);
// Verify
verify(() => mock.stopTimer(any())).called(1);
Coverage Goal
- Repository methods: 100%
- Notifiers/providers: >80%
- Widget tests: at least smoke test per screen
Running Tests
flutter test # all tests
flutter test test/features/timer/ # single feature
flutter test --coverage # with coverage report