Skip to content
Development
Skill

/testing

Use when writing or reviewing Flutter/Dart tests (unit, widget, golden), fixing flaky tests, adding coverage, or choosing between unit and widget tests.

From plugin
flutter-ai-skills
63937 skills
Install
$ npx -y skills add evanca/flutter-ai-rules --skill testing --agent claude-code

How 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/testing

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when writing or reviewing Flutter/Dart tests (unit, widget, golden), fixing flaky tests, adding coverage, or choosing between unit and widget tests.

SKILL.md

testing.SKILL.md
name: testing
description: "Use when writing or reviewing Flutter/Dart tests (unit, widget, golden), fixing flaky tests, adding coverage, or choosing between unit and widget tests."
license: MIT

Testing Skill

Write effective, meaningful Flutter and Dart tests that catch real regressions.

When to Use

Use this skill when:

  • Writing unit tests for business logic, repositories, or utility classes.
  • Writing widget tests for UI components.
  • Reviewing existing tests for correctness and coverage.
  • Fixing flaky or false-positive tests.
  • Deciding between unit tests, widget tests, and integration tests.

---

1. Test Validity

Before writing or accepting a test, ask:

> **"Can this test actually fail if the real code is broken?"**

  • Avoid tests that only confirm mocked/fake behavior without exercising real logic.
  • Avoid tests that confirm behavior guaranteed by the language or standard library.
  • Every test must be capable of catching a real regression.
// BAD — tests the mock, not real logic
test('should return user', () {
  when(() => repo.getUser()).thenReturn(fakeUser);
  expect(repo.getUser(), fakeUser); // Only proves the mock works
});

// GOOD — tests the cubit's state transitions driven by the mock
blocTest<UserCubit, UserState>(
  'should emit loaded state when getUser succeeds',
  build: () {
    when(() => repo.getUser()).thenAnswer((_) async => fakeUser);
    return UserCubit(repo);
  },
  act: (cubit) => cubit.fetchUser(),
  expect: () => [
    const UserState(status: UserStatus.loading),
    UserState(status: UserStatus.loaded, user: fakeUser),
  ],
);

---

2. Structure

Always use `group()` in test files. Name the group after the **class under test**:

group('Counter', () {
  late Counter counter;

  setUp(() {
    counter = Counter();
  });

  test('value should start at 0', () {
    expect(counter.value, 0);
  });

  test('should increment value by 1', () {
    counter.increment();
    expect(counter.value, 1);
  });
});

Rules:

  • Use `setUp` for shared object creation; use `tearDown` for cleanup (closing streams, controllers).
  • Keep each test focused on one behavior.
  • Nest `group()` blocks for sub-features when a class has many methods.

---

3. Naming

Name test cases using **"should"** to describe expected behavior:

test('should emit updated list when item is added', () { ... });
test('should throw ArgumentError when input is negative', () { ... });

---

4. Unit Tests vs Widget Tests

| Type | Target | Tools | |---|---|---| | **Unit test** | Pure Dart logic, repositories, cubits/blocs | `test`, `bloc_test`, `mocktail` | | **Widget test** | Individual widgets, UI behavior, navigation | `flutter_test`, `WidgetTester` |

Default to **unit tests** for business logic. Use **widget tests** when verifying UI rendering, gesture handling, or widget interaction.

---

5. Widget Test Patterns

testWidgets('should display error message on failure', (tester) async {
  await tester.pumpWidget(
    MaterialApp(
      home: BlocProvider<LoginCubit>.value(
        value: mockLoginCubit,
        child: const LoginView(),
      ),
    ),
  );

  // Simulate failure state
  whenListen(
    mockLoginCubit,
    Stream.fromIterable([const LoginState(status: LoginStatus.failure, errorMessage: 'Invalid')]),
    initialState: const LoginState(),
  );
  await tester.pump();

  expect(find.text('Invalid'), findsOneWidget);
});

Rules:

  • Wrap widgets in `MaterialApp` (or the app's root widget) to provide `MediaQuery`, `Directionality`, etc.
  • Use `pump()` for a single frame or `pumpAndSettle()` when animations must complete.
  • Prefer `find.byKey` over `find.text` for widgets that may have localized or dynamic text.

---

6. Mocking Best Practices

  • Use `mocktail` for mocks (no code generation required).
  • Call `registerFallbackValue()` in `setUpAll` for custom types passed to `any()`.
  • Mock at the repository boundary, not at the HTTP/database layer.
class MockAuthRepository extends Mock implements AuthRepository {}

void main() {
  setUpAll(() {
    registerFallbackValue(FakeLoginRequest());
  });

  // ... tests
}

---

7. Test File Organization

test/
  feature_a/
    cubit/
      feature_a_cubit_test.dart
    view/
      feature_a_view_test.dart
    model/
      feature_a_model_test.dart
  • Mirror the `lib/` folder structure under `test/`.
  • One test file per source file.
  • Name test files `<source_file>_test.dart`.
Read more
Ships withflutter-ai-skills

36 Flutter and Dart skills your coding agent loads by itself, sourced only from official documentation. A skill is a folder with a SKILL.md file.

Get the whole plugin
Stats
639
Stars
66
Forks
Active
Maintenance
Shell
Language
MIT
License
3d ago
Last commit
1y ago
Created

Repo: evanca/flutter-ai-rules

Other skills on flutter-ai-skills.