timetracker/.ai/testing.md
2026-08-03 21:51:48 +02:00

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 mocktail when() / 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