About flutter-testing
A testing-strategy skill for Flutter developers, with conventions for test coverage, organization, independence, and naming. It describes golden variant, state matrix, and interaction contract patterns for unit, widget, and integration testing.
Key features
- 01Test pyramid and coverage guidance
- 02Mirrored test-file organization
- 03Independent test conventions
- 04Golden variant testing pattern
- 05State matrix and interaction contract patterns
Use cases
- 01Testing visual variants of a design-system widget
- 02Checking all states of a stateful widget
- 03Verifying reusable widget interaction rules
- 04Running unit, widget, or integration tests
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ dhruvanbhalara/ skills --skill flutter-testingAfter installing, type/flutter-testingin Claude Code to confirm it loaded.
Details
From the project READMETesting Strategy
- Test Pyramid: More unit and widget tests, fewer integration tests. Unit tests are fastest and cheapest.
- Mirror Test Rule: 100% logic and widget coverage. No code without a test.
- Mirror Organization: Test files MUST strictly mirror the
lib/directory structure and end with_test.dart. - Coverage Targets: Target 100% logic coverage for
domainandbloclayers. - Test Independence: Each test MUST be independent. No shared mutable state between tests.
Test Types Overview
| Type | Scope | Speed | Skill |
|---|---|---|---|
| Unit | Single function/class | Fast | dart-testing |
| Widget | Single UI component | Medium | flutter-add-widget-test |
| Integration | Full app / user flow | Slow | flutter-add-integration-test |
Pattern-Based Testing
These three patterns cut repetitive test setup, cover all visual states, and keep widget behavior consistent. They're conventions, not packages.
Golden Variant Testing
When a widget has multiple visual states (primary, disabled, hover, error), test all variants in a single structured group() with a Map<String, Widget Function()>:
- Define a
variantsmap where keys are state names and values are widget builders. - Each variant MUST be rendered in isolation (fresh
pumpWidgetcall per variant). - Use deterministic golden file naming:
goldens/<component>.<variant>.png. - Set a consistent
surfaceSizeviatester.view.physicalSizeto avoid flaky pixel diffs. - When to use: Design system components, widgets with distinct modes/types.
- When NOT to use: Integration tests or animation frame verification.
State Matrix Testing
Every stateful widget MUST be tested against ALL possible UI states. Use a state matrix to separate setup from verification:
- Define a
statesmap with every state the widget can render (loading,error,data,empty). - Write a single
verify(stateName)callback that asserts correct rendering per state usingswitchexpressions. - This pattern prevents the common mistake of only testing the "happy path".
- When to use: Widgets with complex state machines (e.g., BLoC-driven screens).
- When NOT to use: If verification logic varies wildly between states, write separate tests.
Interaction Contract Testing
Reusable widgets have implicit behavioral rules. Define these as explicit, reusable contracts:
- Create helper functions in
test/utils/for common contracts:verifyTappable(tester, finder, mockCallback): Tap fires callback exactly once.verifyDisabledNotTappable(tester, finder, mockCallback): Tap does NOT fire callback when disabled.verifyValidatesOnBlur(tester, finder): Validation triggers when focus leaves.
- Apply contracts consistently across all widgets sharing the same behavior.
- When to use: Widgets with strictly defined behavioral rules that must hold across refactors.
- When NOT to use: One-off logic unique to a single widget.
Test Naming & Structure
- Test Naming: Use string interpolation for test group names:
group('$ClassName',notgroup('ClassName',. This ensures consistency and enables better tooling support. - Test Grouping: Use
group()to organize tests by feature, class, or state for clearer reporting. - Descriptive Names: Test names should clearly describe what is being tested and why.
Common Test Errors
A RenderFlex overflowed...: Wrap widget inExpandedor constrain dimensions in testVertical viewport was given unbounded height: WrapListViewinSizedBoxwith fixed height in testsetState called during build: Defer state changes to post-frame callbackNo MediaQuery widget ancestor: Always wrap test widget inMaterialApp
Running Tests (Quick Reference)
flutter test: Run all unit and widget testsflutter test test/path/to/file_test.dart: Run specific test fileflutter test integration_test/: Run integration testsflutter test --coverage: Run with coverage reportdart test: Pure Dart unit tests