mcpField
F
flutter-tester

flutter-tester

github.com/harishwarriorTesting & quality66423 installsUpdated 15w ago
Repository

About flutter-tester

A testing guidance skill for Flutter projects, covering repositories, DAOs, services, providers, and widgets. It sets out Given-When-Then organization, dependency mocking, test commands, and common pitfalls.

Key features

  1. 01Isolate tests by architecture layer
  2. 02Use Given-When-Then structure
  3. 03Provide Riverpod and widget testing guides
  4. 04Guide mocks, fakes, and dependency overrides
  5. 05Include test commands and checklists

Use cases

  1. 01Write tests for repositories and DAOs
  2. 02Verify Riverpod state and lifecycle
  3. 03Test widget interactions and navigation
  4. 04Check async loading, errors, and edge cases

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/harishwarrior/flutter-claude-skills --skill flutter-tester

After installing, type/flutter-testerin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
layer_testing_patterns.md
riverpod_testing_guide.md
widget_testing_guide.md

Details

From the project README

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

Comments

Markdown supported