Flutter Testing Standards

SkillAI & models

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.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Flutter Testing Standards skill

What this skill tells your AI

The instructions your AI receives, as published by hoangnguyen0403/agent-skills-standard in skills/flutter/flutter-testing/SKILL.md and read by ahel’s review.

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

Signals

GitHub stars
565
Forks
163
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
flutter-testing
Source
github.com/hoangnguyen0403/agent-skills-standard