Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add skills/zakariaf/flutter-skills/testing-strategynpx skills add zakariaf/Flutter-Skills --skill testing-strategygit clone --depth 1 https://github.com/zakariaf/Flutter-SkillsWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/zakariaf/flutter-skills/testing-strategy)<a href="https://agentmods.dev/skills/zakariaf/flutter-skills/testing-strategy"><img src="https://agentmods.dev/badge/skills/zakariaf/flutter-skills/testing-strategy.svg" alt="Measured on agentmods" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00176 | $0.03599 |
| Opus 5 | $0.00088 | $0.01800 |
| Sonnet 5 | $0.00035 | $0.00720 |
| Haiku 4.5 | $0.00018 | $0.00360 |
Grade A, and why
testing-strategy scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 5d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 286 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Testing Strategy
Tests are the only correctness instrument you control at build time: shape the suite
to the code, not to a decades-old ratio, and make each test assert behaviour a build
either passes or fails. Applies to every test under test/ and integration_test/.
Read the reference for the task at hand:
references/test-layers.md— per-layer harness, imports, teardown, edge tables (pure core, in-memory Drift, headless Notifier, integration).references/property-and-fakes.md— fakes-over-mocks, enum-driven fake state, seeded fuzz, independent oracles, absence-of-a-failure-class tests.references/coverage-and-budget.md— file-level floors, the coverage-lies-upward fix, the suite-time budget, and the manual-pass handoff.
Run scripts/check_test_hygiene.sh and scripts/run_tests.sh before a PR.
Golden, RTL, and a11y widget mechanics live in widget-golden-and-a11y-testing; this
skill governs everything below the pixel.
Non-negotiable rules
- Shape the suite to the code, not the pyramid. The 70/20/10 numbers trace to a
2011 test-size heuristic (its author said they were "pulled out of a hat") and
never described Flutter's unit/widget/integration taxonomy. Test at the cheapest
tier that can assert the behaviour: anything expressible as
f(input) -> outputis a unit or property test, never apumpWidget. Driving pure logic through the widget tree is slower, flakier, and hides which layer broke. - Put business rules in a Flutter-free package and inject a
Clock. Domain math lives in pure Dart with zero Flutter/plugin/IO imports, tested withpackage:test(notflutter_test). The one time type ispackage:clock'sClock— NEVERDateTime.now(), never a bespokeClockService. Purecorereads the ambientclock.now(), pinned in tests withwithClock(Clock.fixed(t), …); Riverpod/feature code reads the injectedclockProvider, overridden withclockProvider.overrideWithValue(Clock.fixed(t))(seam owned byvalue-objects-money-and-units). The ban is structural: a pure package declares no Flutter SDK constraint. - Assert invariants, not just examples. Every conversion has a round-trip
test (
decode(encode(x)) == x) and rounding goldens at half-way/boundary values; every universal claim is a seeded fuzz loop (for (var seed = 0; seed < N; seed++)) or property test, checked against an independent oracle — never the production function under test. Print the generated input inreason:so a failure is its own minimal repro.==on integers only;closeTo(x, 1e-9)on doubles. - Test the data layer against a real in-memory engine. Use
NativeDatabase.memory(), never a mocked DAO — a mocked DAO proves nothing about SQL, constraints, indexes, or migrations. Mock repositories only above the data layer.addTearDown(db.close)and close streams synchronously so reactive.watch()streams do not leak "Timer still pending". - Prefer bare-
implementsfakes over mocks for code you own. Aclass FakeX implements X(nonoSuchMethodsuperclass) makes an interface change a compile error, models the risk (state, not call-order) as a field, and doubles as the contract's documentation. Reservemocktailfor genuinely external dependencies; nevermockito/@GenerateMocks(codegen, no null-safety win). registerFallbackValuefor every custom type passed toany()/captureAny()insetUpAll. mocktail throws at runtime, not compile time, on a missing fallback — this is the single most common mocktail failure.- Drive Notifiers headlessly with
ProviderContainer. Override provider dependencies viaoverrideWith; never pump a widget to test state. Assert on the exposedAsyncValue/state, drive actions through.notifier, and dispose the container in teardown. - Guard one end-to-end acceptance gate. A single realistic scenario asserted to
the exact expected result, plus the conservation invariant (parts sum to the
whole). It is the test that proves the pieces compose. Back it with a runtime
assert tripwire inside the primitive itself (
assert(sum(result) == total)) — free in release, catches the bug the moment it happens. - Hold an unrecoverable-bug-files floor by diff-review, not a coverage gate.
There is no automated percentage gate — coverage is a published report
(
ci-pipeline-and-gatesowns that). Instead hold a 100% floor on the handful of files (migrations, the money/allocate primitive, the parser with wire-format traps) where a gap is silent data loss — enforced by reading the diff, not by counting lines. A directory or global percentage gate rewards vanity tests and exclusion churn. First fix the coverage-lies-upward gap:flutter test --coverageomits files no test imports, so the number overstates safety. - Never
pumpAndSettle()on an indefinite animation (splash, shimmer, spinner) — it hangs on a 10-minute timeout. Use timedpump(Duration)withfakeAsync. - Keep the suite fast, and hand structurally-untestable paths to a manual pass. A suite that costs minutes gets skipped, and a skipped suite is a distrusted one. Anything an emulator cannot reproduce (real audio, OEM device diversity, native surfaces without a Flutter engine) is enumerated in a named manual pre-release pass, not faked green — a green test that proves nothing is worse than an admitted gap.
What ships with it
8 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
- examples/allocate_property_test.dart 5.0 KB
- examples/in_memory_drift_test.dart 2.5 KB
- examples/notifier_container_test.dart 3.3 KB
- references/coverage-and-budget.md 5.3 KB
- references/property-and-fakes.md 6.4 KB
- references/test-layers.md 4.9 KB
- scripts/check_test_hygiene.sh 2.9 KB runs code
- scripts/run_tests.sh 1.7 KB runs code
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 5d ago First seen · 286 lines · 176 tokens per session scan A 2e54ec75d735
testing-strategy is a skill published in the GitHub repository zakariaf/Flutter-Skills (2 stars, last pushed 7d ago), licensed MIT. It adds 176 tokens to every session and 3,599 once invoked, about $0.0009 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
Other skills, from other repositories
verify-work
Verify feature, bug, UI, API, mobile, security, or deployment work against acceptance criteria.
flutter-bloc-state-management
Implement BLoC/Cubit state, events, transitions, and async concurrency in Flutter. Use for BLoC/Cubit feature logic, debounced/cancellable events, state rendering, or bloc tests—not generic widget-only work.
angular-testing
Write Angular component tests using TestBed, ComponentHarness, and HttpTestingController with proper signal input handling. Use when writing component tests, mocking HTTP calls, or testing signal inputs.
modernize-tests
Modernize test suites to use modern Swift Testing features or migrate from XCTest.
python-idioms
Python type hints, Protocols, Pydantic, async/await, pytest, ruff, mypy strict.
testing-strategy
Detailed testing reference material: test doubles strategy, integration test infrastructure (Testcontainers, Firebase emulator), naming conventions per language, test organization patterns. Load when writing tests or setting up test infrastructure. The core mandates (TDD, AAA, pyramid) are in the testing-strategy rule…