96 lines
3 KiB
Markdown
96 lines
3 KiB
Markdown
# TT-012 — Unit Tests
|
|
|
|
**Type:** Task
|
|
**Priority:** Medium
|
|
**Labels:** testing, unit-tests
|
|
**Depends on:** TT-004, TT-005
|
|
**Blocks:** —
|
|
|
|
---
|
|
|
|
## Summary
|
|
Write comprehensive unit tests for all repository methods and Riverpod
|
|
notifiers. See `.ai/testing.md` for full conventions.
|
|
|
|
## Scope
|
|
|
|
### Database / Repository tests
|
|
All tests use `NativeDatabase.memory()` — never the real file DB.
|
|
|
|
| Test file | What to test |
|
|
|-----------|-------------|
|
|
| `test/core/database/app_database_test.dart` | Schema creation, schemaVersion |
|
|
| `test/features/projects/projects_repository_test.dart` | CRUD, watchActive stream, archive |
|
|
| `test/features/entries/entries_repository_test.dart` | CRUD, watchByDateRange, getActiveEntry |
|
|
| `test/features/entries/tags_repository_test.dart` | findOrCreate, setTagsForEntry |
|
|
| `test/features/reports/reports_repository_test.dart` | getDurationByProject, getDurationByWeekday |
|
|
|
|
### Notifier tests
|
|
All notifier tests use `ProviderContainer` with mocked repositories.
|
|
|
|
| Test file | What to test |
|
|
|-----------|-------------|
|
|
| `test/features/timer/timer_notifier_test.dart` | start, stop, discard, restore from open entry |
|
|
| `test/features/projects/projects_notifier_test.dart` | create, update, archive, delete |
|
|
| `test/features/entries/entries_notifier_test.dart` | create, update, delete |
|
|
|
|
## Test Patterns
|
|
|
|
### Repository test pattern
|
|
```dart
|
|
late AppDatabase db;
|
|
late DriftProjectsRepository repository;
|
|
|
|
setUp(() {
|
|
db = AppDatabase(NativeDatabase.memory());
|
|
repository = DriftProjectsRepository(db);
|
|
});
|
|
|
|
tearDown(() => db.close());
|
|
|
|
test('insert and retrieve project', () async {
|
|
await repository.create(name: 'Test', colorValue: 0xFF0000FF);
|
|
final projects = await repository.watchActive().first;
|
|
expect(projects, hasLength(1));
|
|
expect(projects.first.name, equals('Test'));
|
|
});
|
|
```
|
|
|
|
### Notifier test pattern
|
|
```dart
|
|
late ProviderContainer container;
|
|
late MockProjectsRepository mockRepo;
|
|
|
|
setUp(() {
|
|
mockRepo = MockProjectsRepository();
|
|
container = ProviderContainer(overrides: [
|
|
projectsRepositoryProvider.overrideWithValue(mockRepo),
|
|
]);
|
|
});
|
|
|
|
tearDown(container.dispose);
|
|
```
|
|
|
|
## Coverage Goals
|
|
| Layer | Target |
|
|
|-------|--------|
|
|
| Repository (CRUD methods) | 100% |
|
|
| Notifiers | ≥ 80% |
|
|
| Export service | ≥ 70% |
|
|
|
|
## Acceptance Criteria
|
|
- [ ] All listed test files exist and pass
|
|
- [ ] `flutter test` exits with code 0
|
|
- [ ] No test uses the real file database
|
|
- [ ] Each repository test covers: insert, read, update, delete, stream emission
|
|
- [ ] `TimerNotifier` test covers: start → running state, stop → idle + entry saved,
|
|
discard → idle + entry deleted, build with open entry → running state restored
|
|
- [ ] `flutter test --coverage` generates coverage report
|
|
|
|
## Running tests
|
|
```bash
|
|
flutter test # all tests
|
|
flutter test test/features/timer/ # single feature
|
|
flutter test --coverage # with lcov coverage
|
|
genhtml coverage/lcov.info -o coverage/html # HTML report
|
|
```
|