# Testing guide
Spark follows the testing model described by the official
[Dart testing documentation](https://dart.dev/tools/testing) and
[Flutter testing overview](https://docs.flutter.dev/testing/overview): keep most
tests fast and isolated, use widget tests for observable UI behavior, and reserve
integration tests for a small number of important end-to-end flows.
## What to test
- Test public behavior and contracts, not private implementation details.
- Prioritize repositories, providers, state transitions, error recovery,
navigation, and interactions that can regress without an analyzer error.
- Cover each meaningful branch once at the lowest useful level. Do not repeat a
repository contract in provider and widget tests unless the higher-level test
verifies distinct wiring or user-visible behavior.
- Prefer one parameterized or table-driven test when cases share the same setup
and assertion shape. Keep separate tests when their failure diagnoses different
behavior.
- Do not add tests for generated code, trivial getters, framework behavior, or
static presentation with no Spark-owned logic.
## Suite balance
Test counts are not a coverage target. New tests should first address an
unrepresented high-risk area rather than deepen an already mature area. In
particular, the video editor suite should grow only for a new gesture, timing,
race, or media-boundary regression.
The optional local coverage summary groups results by `core/` and
`features/` so large imbalances remain visible. Passing
`--enforce-critical` makes the local command fail when a core auth or network
repository implementation has no executed lines. CI runs the test suite without
collecting or enforcing coverage.
## Test quality
- Inject clocks, delays, schedulers, clients, storage, and platform boundaries.
Never wait on wall-clock time when a deterministic seam is possible.
- Use in-memory fakes for owned boundaries and mocks only where interaction
verification is the behavior under test.
- Assert outputs, state, requests, and visible UI. Avoid `verify`-only tests that
merely restate the implementation.
- Keep tests order-independent and clean up provider containers, controllers,
subscriptions, and temporary state.
- Give tests behavioral names so a failure explains the broken contract.
## Commands
Run a targeted file while iterating, then verify the complete suite:
```sh
flutter test test/path/to/example_test.dart
flutter test --test-randomize-ordering-seed=random
flutter test --coverage
dart run tool/coverage_summary.dart coverage/lcov.info --enforce-critical
```
Integration tests live under `integration_test/`, with one file per major user
journey and shared fakes under `integration_test/support/`. Run a journey on a
device with:
```sh
flutter test integration_test/registration_test.dart -d
```
Every journey must keep storage and external-service boundaries isolated from
real user data.