/flutter-testing
Write unit, widget, and integration tests with robot patterns, widget keys, and Patrol in Flutter. Use when implementing test behavior; defer CI-only configuration without test changes.
$ npx -y skills add hoangnguyen0403/agent-skills-standard --skill flutter-testing --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/flutter-testing
Context preview
The summary Claude sees to decide when to auto-load this skill.
Write unit, widget, and integration tests with robot patterns, widget keys, and Patrol in Flutter. Use when implementing test behavior; defer CI-only configuration without test changes.
SKILL.md
flutter-testing.SKILL.mdname: flutter-testing
description: Write unit, widget, and integration tests with robot patterns, widget keys, and Patrol in Flutter. Use when implementing test behavior; defer CI-only configuration without test changes.
metadata:
triggers:
files:
- '**/test/**.dart'
- '**/integration_test/**.dart'
- '**/robots/**.dart'
- 'lib/core/keys/**.dart'
keywords:
- test
- patrol
- robot
- WidgetKeys
- patrolTest
- blocTest
- mocktailFlutter Testing Standards
**Priority: P0 (CRITICAL)**
Core Rules
1. **Test Pyramid**: Unit > Widget > Integration. 2. **Naming**: `should <behavior> when <condition>`. 3. **AAA**: Arrange, Act, Assert in all tests. 4. **Shared Mocks**: `test/shared/` only — no local mocks. 5. **File Placement**: `_integration_test.dart` ONLY in `integration_test/`. 6. **Robot-First**: ALL UI assertions/interactions via **Robot pattern** (e.g., `CheckoutRobot`) — never raw `find.*`/`expect()` in test body.
Widget Testing & Mocking
- **Setup**: Use `TestWrapper.init()` in `setUpAll` and `tester.pumpLocalizedWidget(...)`.
- **Mocking**: Use **GetIt registration** of Mock BLoCs in `setUpAll` if created internally. Use **blocTest** for BLoC logic and **whenListen** for state transitions.
- **Stubbing**: Always stub **bloc.state** and **bloc.stream** in `setUp`. Prohibit `any()` / `anyNamed()`.
- **Async**: Use **settle: false** for loading or stream states to verify mid-process transitions.
Robot Pattern
- All interactions and assertions belong in `*Robot` (e.g., `expectFirstOrderVisible()`).
- Symmetric: every `expectXxxVisible()` needs **expectXxxNotVisible()** pairs.
- **BaseRobot Centralization**: Extract standard scrolling (`scrollDown`, `scrollToEnd`) and screen visibility assertions (`expectScreenVisible`, `expectScreenNotVisible`) into common `BaseRobot` or parent class to avoid duplication.
- Widget tests: include `pumpScreen(bloc:, settle:)` helper.
- **Widget Keys**: Use **WidgetKeys** constants from `lib/core/keys/` — never inline `Key('string')`.
Integration Testing
- Use **patrolTest** with **IntegrationAuthHelper.loginOrSkip($)** for authenticated flows.
- Use **$.native.tap()** or `$.native.*` for native interactions (e.g., system dialogs).
- Create robot: `final robot = OrdersRobot($.tester)` — share same class as widget tests.
- Only `$.native.*` and navigation helpers may remain inline in test body.
Anti-Patterns
- **No inline Key**: Use `WidgetKeys` constant. **No `any()`**: Use typed matchers.
- **No local mocks**: Use `test/shared/`. **No missing bloc stub**: Stub `state` + `stream`.
- **No test-body logic**: Move `find.*`/`expect()` to robot. **No raw find in integration tests**.
- **No `_integration_test.dart` in `test/`**: Rename or merge.
- **No unused imports**: Remove `v_dls` when robots handle assertions. Check Material import needs.
- **No happy-path-only**: Add `Edge cases` group. **No one-sided assertions**: Add `expectNotVisible` pairs.
- **No unchecked text casing**: Verify `.toUpperCase()`, `.tr()` in source.
Verification
- [ ] Fakes used over Mocks for Repositories (well-defined inputs/outputs).
- [ ] Every ViewModel has unit tests covering loading, success, and error states.
- [ ] Every View has widget tests with faked ViewModel.
- [ ] Critical user flows have at least one integration test.
- [ ] `flutter test` passes.
Canonical response anchors
When this skill applies, preserve the following domain terminology or equivalent concrete examples in the answer when relevant:
- GetIt registration
- Register the mock with `GetIt` in `setUpAll` before building the widget under test.
- native interactions
Read more
name: flutter-testing
description: Write unit, widget, and integration tests with robot patterns, widget keys, and Patrol in Flutter. Use when implementing test behavior; defer CI-only configuration without test changes.
metadata:
triggers:
files:
- '**/test/**.dart'
- '**/integration_test/**.dart'
- '**/robots/**.dart'
- 'lib/core/keys/**.dart'
keywords:
- test
- patrol
- robot
- WidgetKeys
- patrolTest
- blocTest
- mocktailFlutter Testing Standards
**Priority: P0 (CRITICAL)**
Core Rules
1. **Test Pyramid**: Unit > Widget > Integration. 2. **Naming**: `should <behavior> when <condition>`. 3. **AAA**: Arrange, Act, Assert in all tests. 4. **Shared Mocks**: `test/shared/` only — no local mocks. 5. **File Placement**: `_integration_test.dart` ONLY in `integration_test/`. 6. **Robot-First**: ALL UI assertions/interactions via **Robot pattern** (e.g., `CheckoutRobot`) — never raw `find.*`/`expect()` in test body.
Widget Testing & Mocking
- **Setup**: Use `TestWrapper.init()` in `setUpAll` and `tester.pumpLocalizedWidget(...)`.
- **Mocking**: Use **GetIt registration** of Mock BLoCs in `setUpAll` if created internally. Use **blocTest** for BLoC logic and **whenListen** for state transitions.
- **Stubbing**: Always stub **bloc.state** and **bloc.stream** in `setUp`. Prohibit `any()` / `anyNamed()`.
- **Async**: Use **settle: false** for loading or stream states to verify mid-process transitions.
Robot Pattern
- All interactions and assertions belong in `*Robot` (e.g., `expectFirstOrderVisible()`).
- Symmetric: every `expectXxxVisible()` needs **expectXxxNotVisible()** pairs.
- **BaseRobot Centralization**: Extract standard scrolling (`scrollDown`, `scrollToEnd`) and screen visibility assertions (`expectScreenVisible`, `expectScreenNotVisible`) into common `BaseRobot` or parent class to avoid duplication.
- Widget tests: include `pumpScreen(bloc:, settle:)` helper.
- **Widget Keys**: Use **WidgetKeys** constants from `lib/core/keys/` — never inline `Key('string')`.
Integration Testing
- Use **patrolTest** with **IntegrationAuthHelper.loginOrSkip($)** for authenticated flows.
- Use **$.native.tap()** or `$.native.*` for native interactions (e.g., system dialogs).
- Create robot: `final robot = OrdersRobot($.tester)` — share same class as widget tests.
- Only `$.native.*` and navigation helpers may remain inline in test body.
Anti-Patterns
- **No inline Key**: Use `WidgetKeys` constant. **No `any()`**: Use typed matchers.
- **No local mocks**: Use `test/shared/`. **No missing bloc stub**: Stub `state` + `stream`.
- **No test-body logic**: Move `find.*`/`expect()` to robot. **No raw find in integration tests**.
- **No `_integration_test.dart` in `test/`**: Rename or merge.
- **No unused imports**: Remove `v_dls` when robots handle assertions. Check Material import needs.
- **No happy-path-only**: Add `Edge cases` group. **No one-sided assertions**: Add `expectNotVisible` pairs.
- **No unchecked text casing**: Verify `.toUpperCase()`, `.tr()` in source.
Verification
- [ ] Fakes used over Mocks for Repositories (well-defined inputs/outputs).
- [ ] Every ViewModel has unit tests covering loading, success, and error states.
- [ ] Every View has widget tests with faked ViewModel.
- [ ] Critical user flows have at least one integration test.
- [ ] `flutter test` passes.
Canonical response anchors
When this skill applies, preserve the following domain terminology or equivalent concrete examples in the answer when relevant:
- GetIt registration
- Register the mock with `GetIt` in `setUpAll` before building the widget under test.
- native interactions
The portable SDLC standards layer for AI coding agents. Sync once, then work in your own runtime.
Repo: hoangnguyen0403/agent-skills-standard
Other skills on agent-skills-standard.
- /android-agp-upgrade
Upgrade an Android project to Android Gradle Plugin (AGP) 9. Use when migrating to AGP 9, updating Gradle build files, migrating to built-in Kotlin, or adopting the new AGP DSL.
Open skill - /android-architecture
Apply Clean Architecture layering, modularization, and Unidirectional Data Flow in Android projects. Use when setting up project structure, placing code in layers, configuring feature/core modules, or implementing UDF patterns; defer Compose state and ViewModel/StateFlow
Open skill - /android-background-work
Implement WorkManager and background processing correctly on Android. Use when creating Worker classes, scheduling tasks, choosing between WorkManager and Foreground Services, or setting up Hilt in workers; defer FCM and notification delivery to android-notifications.
Open skill - /android-compose-migration
Migrate an Android XML View to Jetpack Compose following a structured 10-step workflow. Use when converting XML layouts to Compose, setting up Compose in an existing View-based project, or incrementally adopting Compose.
Open skill - /android-compose
Build high-performance declarative UI with Jetpack Compose. Use when writing Composable functions, optimizing recomposition, hoisting state, or working with LazyColumn and side effects; defer deep-link and navigation routing to android-navigation.
Open skill - /android-concurrency
Write correct coroutine scopes, lifecycle collection, and dispatcher injection in Android production code. Use for suspend functions, coroutine scopes, and dispatcher mechanics; defer ViewModel StateFlow/LiveData architecture, Fragment lifecycle recipes,
Open skill

