Skillshub flutter-testing
Unit, widget, and integration testing with robots, widget keys, and Patrol. Use when writing Flutter unit tests, widget tests, or integration tests with Patrol. (triggers: **/test/**.dart, **/integration_test/**.dart, **/robots/**.dart, lib/core/keys/**.dart, test, patrol, robot, WidgetKeys, patrolTest, blocTest, mocktail)
install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/HoangNguyen0403/agent-skills-standard/flutter-testing" ~/.claude/skills/comeonoliver-skillshub-flutter-testing && rm -rf "$T"
manifest:
skills/HoangNguyen0403/agent-skills-standard/flutter-testing/SKILL.mdsource content
Flutter Testing Standards
Priority: P0 (CRITICAL)
Core Rules
- Test Pyramid: Unit > Widget > Integration.
- Naming:
.should <behavior> when <condition> - AAA: Arrange, Act, Assert in all tests.
- Shared Mocks:
only — no local mocks.test/shared/ - File Placement:
ONLY in_integration_test.dart
.integration_test/ - Robot-First: ALL UI assertions/interactions via Robot pattern (e.g.,
) — never rawCheckoutRobot
/find.*
in test body.expect()
Widget Testing & Mocking
- Setup: Use
inTestWrapper.init()
andsetUpAll
.tester.pumpLocalizedWidget(...) - Mocking: Use GetIt registration of Mock BLoCs in
if created internally. Use blocTest for BLoC logic and whenListen for state transitions.setUpAll - Stubbing: Always stub bloc.state and bloc.stream in
. ProhibitsetUp
/any()
.anyNamed() - Async: Use settle: false for loading or stream states to verify mid-process transitions.
Robot Pattern
- All interactions and assertions belong in
(e.g.,*Robot
).expectFirstOrderVisible() - Symmetric: every
needs expectXxxNotVisible() pairs.expectXxxVisible() - Widget tests: include a
helper.pumpScreen(bloc:, settle:) - Widget Keys: Use WidgetKeys constants from
— never inlinelib/core/keys/
.Key('string')
Integration Testing
- Use patrolTest with IntegrationAuthHelper.loginOrSkip($) for authenticated flows.
- Use $.native.tap() or
for native interactions (e.g., system dialogs).$.native.* - Create a robot:
— share the same class as widget tests.final robot = OrdersRobot($.tester) - Only
and navigation helpers may remain inline in the test body.$.native.*
Anti-Patterns
- No inline Key: Use
constant. NoWidgetKeys
: Use typed matchers.any() - No local mocks: Use
. No missing bloc stub: Stubtest/shared/
+state
.stream - No test-body logic: Move
/find.*
to robot. No raw find in integration tests.expect() - No
in_integration_test.dart
: Rename or merge.test/ - No unused imports: Remove
when robots handle assertions. Check Material import needs.v_dls - No happy-path-only: Add
group. No one-sided assertions: AddEdge cases
pairs.expectNotVisible - No unchecked text casing: Verify
,.toUpperCase()
in source..tr()