mcpField
D
dart-migrate-to-checks-package

dart-migrate-to-checks-package

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

dart-migrate-to-checks-package について

dart-migrate-to-checks-packageは、Dartのテストをpackage:matcherからpackage:checksへ移行する開発者向けのスキルです。アサーション構文の対応を示し、FutureとStreamの非同期検証も扱います。

主な機能

  1. 01一般的なアサーション構文の対応
  2. 02依存関係とインポート変更の案内
  3. 03カスケードによるプロパティ検査
  4. 04Futureの非同期アサーション解説
  5. 05Streamの順次アサーション解説
  6. 06移行検証チェックリスト

活用シーン

  1. 01expectアサーションをcheckへ変換
  2. 02FutureとStreamのテストを書き換え
  3. 03移行後の解析とテストを確認

インストール

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

$npx skills add https://github.com/dhruvanbhalara/skills --skill dart-migrate-to-checks-package

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

詳細

目次

package:checks に移行する理由

package:checks は、Dart チームがメンテナンスしている最新のアサーションライブラリで、package:matcher に代わるものです。従来のマッチャーに比べて、次のようなメリットがあります。

  • 流暢な API:ネストしたヘルパー関数の代わりに Dart のメソッドを使い、自然にアサーションを連鎖できます。
  • 型安全性:期待されるプロパティに対するコンパイラのチェックを活用でき、テストでの型の不一致を防げます。
  • わかりやすい診断情報:何が、なぜ失敗したのかを正確に示す、非常に明確な失敗メッセージを確認できます(例:コレクションの差異を表示します)。

依存関係の管理

パッケージに checks ライブラリを追加するには、次の手順に従います。

  1. ターミナルを使って、checks を dev_dependency として追加します。
    dart pub add dev:checks
    
  2. 移行対象のすべてのテストファイルで、メインパッケージのエントリーポイントをインポートします。
    import 'package:checks/checks.dart';
    
  3. pubspec.yaml から package:matcher の明示的な依存関係を削除します(package:test は推移的にマッチャーをインポートしますが、これは問題ありません)。

アサーションの対応関係と構文のガイドライン

次の対応関係に従って、従来のアサーションを移行します。

シナリオ従来のマッチャー(package:matcher)最新の checks(package:checks)
等価性expect(value, equals(expected))check(value).equals(expected)
同一性expect(value, same(expected))check(value).identicalTo(expected)
型チェックexpect(value, isA<Type>())check(value).isA<Type>()
null 判定expect(value, isNull)check(value).isNull()
真偽値expect(value, isTrue)check(value).isTrue()
包含expect(list, contains(item))check(list).contains(item)
文字列の接頭辞expect(str, startsWith(prefix))check(str).startsWith(prefix)
プロパティのチェックexpect(user.name, equals('Alice'))check(user).has((u) => u.name, 'name').equals('Alice')
複数のチェックの連鎖

同じ対象に対して個別の期待値ステートメントを書かずに複数のプロパティを検証するには、Dart のカスケード演算子(..)を使います。

check(user)
  ..has((u) => u.name, 'name').equals('Alice')
  ..has((u) => u.age, 'age').isGreaterThan(20);

高度な非同期アサーション

1. Future

Future の解決を検証するには、基本となる check ステートメントを必ず await します。

// Verify completion value:
await check(fetchScore()).completes((score) => score.equals(100));

// Verify throws error:
await check(failingTask()).throws<HttpException>().has((e) => e.statusCode, 'statusCode').equals(500);
2. Stream

Stream が出力する複数の項目を順番に検証するには、対象のストリームを package:async の StreamQueue でラップします。

import 'package:async/async.dart';

final queue = StreamQueue(eventStream);
await check(queue).emits((event) => event.equals('first_event'));
await check(queue).emits((event) => event.equals('second_event'));

ワークフロー:構文移行の実行

テストスイートを移行する際は、次のチェックリストに従います。

  • 依存関係の設定:dev:checks をインストールし、dart pub get を実行します。
  • 対象ファイルの検索:従来の expect() 呼び出しを含むテストファイルを見つけます。
  • インポートの更新:matcher のインポートを置き換えるか、import 'package:checks/checks.dart' を追加します。
  • 単純なケースの変換:基本的な等価性と型の一致を expect から check に変換します。
  • カスケードによる最適化:同じオブジェクトを対象とする複数のアサーションをカスケードにまとめます。
  • 非同期呼び出しの更新:Future/Stream の非同期チェックを書き換え、await と completes() クロージャーを使います。
  • コンパイラチェックの検証:dart analyze を実行し、型の不一致に関する警告を解消します。
  • テストの実行:dart test を実行し、移行したすべてのアサーションが正常に実行されることを確認します。

例

移行の比較

この例では、従来の matcher 構文から最新の checks 構文へ、完全で忠実度の高いユーザープロフィールのテストケースを移行する方法を示します。

// --- Legacy Matcher Assertion Style ---
import 'package:test/test.dart';

class Account {
  final String email;
  final List<String> tags;
  Account(this.email, this.tags);
}

void badTest() {
  final account = Account('[email protected]', ['admin', 'tier1']);

  expect(account.email, equals('[email protected]'));
  expect(account.tags, contains('admin'));
  expect(account.tags.length, equals(2));
}

// --- Modern Checks Assertion Style ---
import 'package:checks/checks.dart';

void goodTest() {
  final account = Account('[email protected]', ['admin', 'tier1']);

  // Chain validations cleanly using cascades and property extractors
  check(account)
    ..has((a) => a.email, 'email').equals('[email protected]')
    ..has((a) => a.tags, 'tags').contains('admin')
    ..has((a) => a.tags.length, 'tags length').equals(2);
}
例外と Future の完了のテスト
import 'package:checks/checks.dart';
import 'package:test/test.dart';

Future<String> fetchRole(bool fail) async {
  await Future.delayed(const Duration(milliseconds: 10));
  if (fail) throw StateError('Fetch failed');
  return 'Manager';
}

void main() {
  group('Asynchronous Tests', () {
    test('verifies successful completion', () async {
      await check(fetchRole(false)).completes(
        (role) => role.equals('Manager'),
      );
    });

    test('verifies throwing specific state errors', () async {
      await check(fetchRole(true)).throws<StateError>().has(
        (e) => e.message, 'message',
      ).equals('Fetch failed');
    });
  });
}

コメント