agentleFS
HarishwarriorHarishwarrior/flutter-claude-skills/flutter-tester/SKILL.md

flutter-tester

Skill68 starsChanged 7 months agoMITView on GitHub

Use when creating, writing, fixing, or reviewing tests in a Flutter project. Covers unit tests, widget tests, integration tests, Riverpod provider testing, and Mockito mocking. Provides Given-When-Then patterns, layer isolation strategies, and test setup for GetIt, SharedPreferences, and FakeDatabase.

3 other projects use a version of this, 2 of them edited.

Adopted by

Most recently taken up by

  • Other versions3 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 2

    1. FNOSP/FlyNarwhal★ 51997% same
    2. FNOSP/fntv-client-multiplatform★ 51997% same

    Wrote their own version · 1

    1. Namma-Flutter/namma_wallet★ 59same name

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • In this repository2 other files it gives its agents.

The file

We split this skill into the rules it gives an agent

4 rules. 2 are common, 0 are distinctive, and 2 are very specific to this project.

  • 2

    Common

    Most of the 3 edited versions we read keep these.

  • 0

    Distinctive

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Run dart run build_runner build to generate mocks after adding @GenerateMocks annotations

    line 15
  2. Common:

    Test each architectural layer in isolation using Given-When-Then structure.

    line 20
  3. Common:

    Test each layer against its own mocked dependencies:

    line 36
  4. Very specific:

    Run dart run build_runner build after modifying @GenerateMocks.

    line 85

“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Flutter Tester

Requirements

  • Flutter project with flutter_test dependency
  • Works with Riverpod, Mockito, and GetIt
  • Run dart run build_runner build to generate mocks after adding @GenerateMocks annotations
  • Compatible with FVM (fvm flutter test instead of flutter test)

Overview

Test each architectural layer in isolation using Given-When-Then structure. Always test both success and error paths. Never mock providers — override their dependencies instead.

Reference Files

Load the relevant file based on what you're testing:

What you're testingReference file
Repository, DAO, Service logicreferences/layer_testing_patterns.md
Widget UI, interactions, dialogs, navigationreferences/widget_testing_guide.md
Riverpod provider state, mutations, lifecyclereferences/riverpod_testing_guide.md

Core Principles

1. Layer Isolation

Test each layer against its own mocked dependencies:

LayerWhat to testWhat to mock
RepositoryData coordination between sourcesDAOs, APIs, Logger
DAODatabase CRUD operationsUse real in-memory DB, mock Logger
ProviderState management and transitionsServices, Repositories
ServiceBusiness logic and workflowsRepositories, Network clients
WidgetUI behaviour and interactionsProvider dependencies (via overrides)

2. Given-When-Then Structure

test('Given valid data, When fetchUsers called, Then returns user list', () async {
  // Arrange (Given)
  when(mockDAO.fetchAll()).thenAnswer((_) async => expectedUsers);

  // Act (When)
  final result = await repository.fetchUsers();

  // Assert (Then)
  expect(result, equals(expectedUsers));
  verify(mockDAO.fetchAll()).called(1);
});

3. Test Organisation

group('UserRepository', () {
  group('fetchUsers', () {
    setUp(() { /* init mocks, register with GetIt */ });
    tearDown(() => GetIt.I.reset()); // Always reset GetIt

    test('Given success ... When ... Then ...', () { });
    test('Given error  ... When ... Then ...', () { });
  });
});

Standard Test Setup

Generate Mocks

@GenerateMocks([IUserDAO, IUserAPI, ILogger])
void main() { ... }

Run dart run build_runner build after modifying @GenerateMocks.

Register with GetIt

setUp(() {
  mockDAO = MockIUserDAO();
  mockLogger = MockILogger();
  GetIt.I
    ..registerSingleton<IUserDAO>(mockDAO)
    ..registerSingleton<ILogger>(mockLogger);
});

tearDown(() => GetIt.I.reset()); // Critical — always reset

Fakes vs Mocks

  • Fakes (class FakeLogger extends ILogger) — silent stubs; use when you don't need to verify calls
  • Mocks (MockILogger) — use when you need when(), verify(), or thenThrow()

Quick Reference

ScenarioKey pattern
Test a repositoryMock DAO + API → inject into repository constructor
Test a DAOFakeDatabase or openInMemoryDatabase() in setUp, delete table in tearDown
Test a Riverpod providercreateContainer(overrides: [serviceProvider.overrideWith(...)])
Test a widgetSet screen size, use find.byKey(), call pumpAndSettle()
Test a loading stateUse Completer, pump() to assert loading, complete, pump() again
Test platform-specific UIdebugDefaultTargetPlatformOverride = TargetPlatform.iOS — reset after
Test GoRouter navigationFakeGoRouter + MockGoRouterProvider

Running Tests

flutter test --coverage                       # All tests with coverage
flutter test test/path/to/test.dart           # Specific file
flutter test --plain-name "Given valid data"  # Filter by name
genhtml coverage/lcov.info -o coverage/html   # Generate HTML coverage report
# Prefix any command with `fvm` if using Flutter Version Manager

Common Mistakes

MistakeFix
Mocking a provider directlyOverride its dependencies: provider.overrideWith(...)
Missing GetIt.I.reset() in tearDownTests pollute each other — always reset
await Future.delayed() in testsUse await tester.pumpAndSettle() or Completer instead
Finding widgets by text stringUse find.byKey(const Key('name')) — stable across text changes
No screen size in widget testsAdd tester.view.physicalSize = const Size(1000, 1000)
Not resetting debugDefaultTargetPlatformOverrideSet to null at the end of the test
tearDown() without a lambdaWrite tearDown(() async { ... }) not tearDown() async { ... }

Test Checklist

Setup & Mocking:

  • Dependencies mocked (not providers)
  • SharedPreferences mocked if used
  • GetIt.I.reset() in tearDown
  • Streams closed in tearDown
  • Controllers disposed in tearDown

Widget Tests:

  • Keys added to source widgets and used in find.byKey()
  • Screen size set (physicalSize + devicePixelRatio)
  • Platform overrides reset (debugDefaultTargetPlatformOverride = null)
  • Navigation verified if applicable

Test Coverage:

  • Success and failure paths covered
  • Edge cases tested (null, empty, max values)
  • Loading and error states tested
  • Async handled correctly (no Future.delayed)

Code Quality:

  • Given-When-Then naming used
  • verify() or verifyNever() where appropriate
  • Tests are isolated and deterministic

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.