mcpField
F
flutter-tester

flutter-tester

github.com/harishwarriorテスト・品質66423 回インストール15 週間前に更新
リポジトリ

flutter-tester について

Flutter プロジェクト向けに、Repository、DAO、サービス、Provider、Widget のテスト方法を示すスキルです。Given-When-Then による構成、依存関係のモック、実行コマンド、よくあるミスを扱います。

主な機能

  1. 01アーキテクチャ層ごとのテスト分離
  2. 02Given-When-Then 形式の利用
  3. 03Riverpod と Widget のテストガイド
  4. 04モック、Fake、依存関係の上書き方法
  5. 05テストコマンドとチェックリスト

活用シーン

  1. 01Repository と DAO のテスト作成
  2. 02Riverpod の状態とライフサイクルの検証
  3. 03Widget の操作とナビゲーションのテスト
  4. 04非同期処理、エラー、境界状態の確認

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/flutter-testerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
layer_testing_patterns.md
riverpod_testing_guide.md
widget_testing_guide.md

詳細

Flutter テスター

要件

  • flutter_test 依存関係を含む Flutter プロジェクト
  • Riverpod、Mockito、GetIt と連携します
  • @GenerateMocks アノテーションを追加した後、dart run build_runner build を実行してモックを生成します
  • FVM と互換性があります(flutter test の代わりに fvm flutter test を使用します)

概要

Given-When-Then 構成を使って、各アーキテクチャ層を個別にテストします。成功パスとエラーパスの両方を必ずテストしてください。プロバイダーはモックせず、依存関係をオーバーライドしてください。

参照ファイル

テスト対象に応じて、該当するファイルを読み込んでください。

テスト対象参照ファイル
リポジトリ、DAO、サービスのロジックreferences/layer_testing_patterns.md
ウィジェットの UI、操作、ダイアログ、ナビゲーションreferences/widget_testing_guide.md
Riverpod プロバイダーの状態、変更、ライフサイクルreferences/riverpod_testing_guide.md

基本原則

1. レイヤーの分離

各レイヤーを、それぞれのモック依存関係に対してテストします。

レイヤーテスト対象モック対象
リポジトリデータソース間のデータ調整DAO、API、ロガー
DAOデータベースの CRUD 操作インメモリ DB を実際に使用し、ロガーはモックします
プロバイダー状態管理と遷移サービス、リポジトリ
サービスビジネスロジックとワークフローリポジトリ、ネットワーククライアント
ウィジェットUI の動作と操作プロバイダーの依存関係(オーバーライド経由)
2. Given-When-Then 構成
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. テストの構成
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 ...', () { });
  });
});

標準的なテストのセットアップ

モックの生成
@GenerateMocks([IUserDAO, IUserAPI, ILogger])
void main() { ... }

@GenerateMocks を変更した後、dart run build_runner build を実行します。

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

tearDown(() => GetIt.I.reset()); // Critical — always reset
フェイクとモック
  • フェイク(class FakeLogger extends ILogger)— 呼び出しを検証する必要がない場合に使う、何もしないスタブです
  • モック(MockILogger)— when()、verify()、thenThrow() が必要な場合に使います

クイックリファレンス

シナリオ主なパターン
リポジトリをテストするDAO + API をモックし、リポジトリのコンストラクターに注入します
DAO をテストするsetUp で FakeDatabase または openInMemoryDatabase() を使い、tearDown でテーブルを削除します
Riverpod プロバイダーをテストするcreateContainer(overrides: [serviceProvider.overrideWith(...)])
ウィジェットをテストする画面サイズを設定し、find.byKey() を使って、pumpAndSettle() を呼び出します
ローディング状態をテストするCompleter を使い、pump() でローディング状態を検証し、完了させてから再度 pump() を呼び出します
プラットフォーム固有の UI をテストするdebugDefaultTargetPlatformOverride = TargetPlatform.iOS — テスト後にリセットします
GoRouter のナビゲーションをテストするFakeGoRouter + MockGoRouterProvider

テストの実行

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

よくある間違い

間違い修正方法
プロバイダーを直接モックする依存関係をオーバーライドします:provider.overrideWith(...)
tearDown で GetIt.I.reset() を呼び出していないテスト同士が干渉します — 必ずリセットしてください
テストで await Future.delayed() を使う代わりに await tester.pumpAndSettle() または Completer を使います
テキスト文字列でウィジェットを検索するfind.byKey(const Key('name')) を使います — テキストが変わっても安定します
ウィジェットテストで画面サイズを設定していないtester.view.physicalSize = const Size(1000, 1000) を追加します
debugDefaultTargetPlatformOverride をリセットしていないテストの最後に null を設定します
ラムダなしで tearDown() を使うtearDown() async { ... } ではなく tearDown(() async { ... }) と記述します

テストチェックリスト

セットアップとモック:

  • 依存関係をモック化している(プロバイダーではない)
  • 使用している場合は SharedPreferences をモック化している
  • tearDown で GetIt.I.reset() を呼び出している
  • tearDown でストリームを閉じている
  • tearDown でコントローラーを破棄している

ウィジェットテスト:

  • ソースウィジェットにキーを追加し、find.byKey() で使用している
  • 画面サイズを設定している(physicalSize と devicePixelRatio)
  • プラットフォームのオーバーライドをリセットしている(debugDefaultTargetPlatformOverride = null)
  • 該当する場合はナビゲーションを検証している

テストカバレッジ:

  • 成功パスと失敗パスをカバーしている
  • エッジケースをテストしている(null、空、最大値)
  • 読み込み状態とエラー状態をテストしている
  • 非同期処理を適切に扱っている(Future.delayed を使用していない)

コード品質:

  • Given-When-Then の命名を使用している
  • 適切な箇所で verify() または verifyNever() を使用している
  • テストが分離され、決定論的である

コメント