Pest v3リリース

本日、Pest 3のリリースを発表できることを嬉しく思います。Laracon USで発表したように、Pest 3では、ミューテーションテスト、アーキテクチャプリセット、チーム管理、新しい設定API、アーキテクチャテストの様々な改善などが導入されています。

Pestの開発者であるNuno Maduroによる、Pest 3の新機能デモをご覧ください。

以下では、このリリースに関する詳細について説明します。いつものように、アップグレードガイドはウェブサイトで確認できます。

ミューテーションテスト

ミューテーションテストは、コードに小さな変更(ミューテーション)を加え、テストがそれらを検出できるかどうかを確認する革新的な新技術です。これにより、コードカバレッジの達成だけでなく、テストの実際の品質についても、アプリケーションを徹底的にテストできます。テストスイートの弱点を見つけて品質を向上させるための優れた方法です。

Mutation Testing

ミューテーションテストを開始するには、テストファイルに移動し、covers()関数を使用して、テストがコードのどの部分をカバーしているかを具体的に指定します。

1covers(TodoController::class);
2 
3it('list todos', function () {
4 $this->getJson('/todos')->assertStatus(200);
5});

次に、--mutateオプションを付けてPest PHPを実行して、ミューテーションテストを開始します。

1./vendor/bin/pest --mutate
2# or in parallel...
3./vendor/bin/pest --mutate --parallel

Pestは、「変更された」コードに対してテストを再実行し、テストがまだパスしているかどうかを確認します。ミューテーションに対してテストがまだパスしている場合、そのテストはそのコードの特定の部分をカバーしていません。その結果、Pestはミューテーションとコードの差分を出力します。

1UNTESTED app/Http/TodoController.php > Line 44: ReturnValue - ID: 76d17ad63bb7c307
2 
3class TodoController {
4 public function index(): array
5 {
6 // pest detected that this code is untested because
7 // the test is not covering the return value
8- return Todo::all()->toArray();
9+ return [];
10 }
11}
12 
13 Mutations: 1 untested
14 Score: 33.44%

テストされていないコードを特定したら、それをカバーする追加のテストを作成できます。

1covers(TodoController::class);
2 
3it('list todos', function () {
4+ Todo::factory()->create(['name' => 'Buy milk']);
5 
6- $this->getJson('/todos')->assertStatus(200);
7+ $this->getJson('/todos')->assertStatus(200)->assertJson([['name' => 'Buy milk']]);
8});

次に、--mutateオプションを付けてPestを再実行し、ミューテーションが「テスト済み」でカバーされているかどうかを確認します。

1Mutations: 1 tested
2Score: 100.00%

ミューテーションスコアが高いほど、テストスイートの品質は高くなります。100%のミューテーションスコアは、すべてのミューテーションが「テスト済み」であることを意味し、ミューテーションテストの目標です。

「テストされていない」または「未カバー」のミューテーションが見つかった場合、またはミューテーションスコアが100%を下回る場合は、通常、テストが不足しているか、テストがすべての例外ケースをカバーしていないことを意味します。

当社のプラグインはPest PHPに深く統合されています。そのため、ミューテーションが導入されるたびに、Pest PHPは

  • 変更されたコードをカバーするテストのみを実行して、処理速度を向上させます。
  • 可能な限りキャッシュを使用して、後続の実行速度を向上させます。
  • 有効になっている場合、並列実行を使用して複数のテストを並列で実行して、処理速度を向上させます。

@pest-mutate-ignore--mutate --everythingなど、ミューテーションテストでさらに多くの機能があります。ミューテーションテストセクションで詳細を確認できます。

アーキテクチャプリセット

ご存知のとおり、アーキテクチャテストを使用すると、アプリケーションがアーキテクチャルールのセットに従っているかどうかをテストする期待値を指定でき、クリーンで持続可能なコードベースの維持に役立ちます。

Pestで最も人気のある機能の1つであり、Pest 3ではアーキテクチャプリセットを導入しています。アーキテクチャプリセットは、アプリケーションのアーキテクチャをテストするために使用できる、事前に定義されたアーキテクチャルールのセットです。これらのプリセットは、アーキテクチャテストを迅速かつ簡単に開始できるように設計されています。

Arch Presets

Pest 3で使用可能なアーキテクチャプリセットを以下に示します。

php

phpプリセットは、任意のPHPプロジェクトで使用できる、事前に定義された期待値のセットです。フレームワークやライブラリには依存しません。

dievar_dump、および同様の関数の使用を避け、非推奨のPHP関数を使用していないことを確認します。ソースコード

1arch()->preset()->php();

security

securityプリセットは、任意のPHPプロジェクトで使用できる、事前に定義された期待値のセットです。フレームワークやライブラリには依存しません。

evalmd5、および同様の関数など、セキュリティの脆弱性につながる可能性のあるコードを使用していないことを確認します。ソースコード

1arch()->preset()->security();

laravel

laravelプリセットは、Laravelプロジェクトで使用できる、事前に定義された期待値のセットです。

プロジェクトの構造が、よく知られているLaravelの規約に従っていることを確認します。たとえば、コントローラーはindexshowcreatestoreeditupdatedestroyを公開メソッドとしてのみ持ち、常にControllerで終わるなど。ソースコード

1arch()->preset()->laravel();

strict

strictプリセットは、任意のPHPプロジェクトで使用できる、事前に定義された期待値のセットです。フレームワークやライブラリには依存しません。

すべてのファイルで厳密な型を使用していること、すべてのクラスがfinalであることなどを確認します。ソースコード

1arch()->preset()->strict();

relaxed

relaxedプリセットは、任意のPHPプロジェクトで使用できる、事前に定義された期待値のセットです。フレームワークやライブラリには依存しません。

strictプリセットとは逆で、すべてのファイルで厳密な型を使用していないこと、すべてのクラスがfinalではないことなどを確認します。ソースコード

1arch()->preset()->relaxed();

通常のアーキテクチャテストと同様に、ignoring()メソッドを使用して特定の期待値ターゲットを無視できます。

1arch()->preset()->security()->ignoring('md5');
2 
3arch()->preset()->laravel()->ignoring(User::class);

アーキテクチャプリセットの使用方法については、アーキテクチャテストセクションを参照してください。

チーム管理

Pest 3では、チーム管理も導入されています。これは、コンソールから直接チームとタスクやTODOを管理できる新機能です。チーム管理を使用すると、タスクの作成、割り当て、追跡、および各タスクのステータスの表示を行うことができます。

Team Management

Pestでチーム管理を開始するには、Pest.php設定ファイルにプロジェクトのURLを指定する必要があります。このURLは、TODOを対応するプロジェクト管理システムにリンクするために使用されます。

1pest()->project()->github('my-organization/my-repository');

異なるバージョン管理システムを使用している場合は、代わりにgitlabbitbucketjira、またはcustomメソッドを使用できます。

最後に、todo()メソッドを使用してTODOを作成できます。また、assigneeissue引数を使用して、TODOを特定のチームメンバーに割り当てたり、プロジェクト管理システムの課題にリンクしたりできます。

1it('has a contact page', function () {
2 //
3})->todo(assignee: 'taylor@laravel.com', issue: 123);

TODOに追加のコンテキストを提供することも役立つことがよくあります。Pestでは、todo()メソッドのnote引数に文字列を提供することで、TODOのメモを書くことができます。

1it('has a contact page', function () {
2 //
3})->todo(note: <<<NOTE
4 Given I am a user
5 When I visit the contact page
6 Then I should see a contact form
7NOTE);

TODOが完了したら、wip()メソッドを使用して作業中としてマークしたり、done()メソッドを使用して完了としてマークしたりできます。

1it('has a contact page', function () {
2 //
3})->wip(assignee: 'taylor@laravel.com', issue: 123); // or ->done()

最後に、Pestの実行時に--todosオプションを含めることで、テストスイートの他の部分とは別にTODOを表示できます。また、--assigneeオプションに名前を提供することで担当者別にTODOをフィルタリングしたり、--issueオプションに課題番号を提供することで課題別にTODOをフィルタリングしたりすることもできます。

1./vendor/bin/pest --todos --assignee=taylor # or --issue=123

チーム管理ではさらに多くの機能があります。チーム管理セクションで詳細を確認できます。

新しい設定API

Pest 1/Pest 2の設定APIはやや分かりにくく、元々テストケースインスタンスにバインドされたクロージャ内で$this変数を持つためだけに作られたuses()関数が、ほぼすべての用途で使用されていました。

Pest 3では、より直感的で使いやすい新しい設定APIを導入しました。新しい設定APIはpest()関数に基づいており、流暢で表現力豊かなAPIを使用してPestを設定できます。

注:uses()関数はPest 3でも使用できます。削除する予定はありません。ただし、新しいプロジェクトでは新しい設定APIを使用することをお勧めします。

1-uses(TestCase::class)->in(__DIR__);
2+pest()->extends(TestCase::class);
3 
4-uses(TestCase::class, RefreshDatabase::class)->in('Features');
5+pest()->extends(TestCase::class)->use(RefreshDatabase::class)->in('Features');
6 
7-uses()->compact();
8+pest()->printer()->compact();

もちろん、uses() APIで使用可能なメソッド(->beforeEach()->group()など)は、新しいpest()設定APIでも使用できます。直感的に使いやすくなりました。

アーキテクチャテストのさらなる改善

新しい期待値

改めてですが、Pestには多くの新しいアーキテクチャに関する期待事項と改善点が含まれています。その一部は新しいArchプリセットですでに使用されていますが、個別に使用することもできます。

  • toUseStrictEquality() - 厳密な等価性を用いることをアサートします。==ではなく===を使用します。
  • toHaveMethodsDocumented() - クラスのすべてのメソッドがドキュメント化されていることをアサートします。
  • toHavePropertiesDocumented() - クラスのすべてのプロパティがドキュメント化されていることをアサートします。
  • toHaveFileSystemPermissions() - ファイルが期待されるファイルシステム権限を持っていることをアサートします。
  • toHaveLineCountLessThan - ファイルが行数の指定された数より少ないことをアサートします。
  • toHaveMethods() - クラスが期待されるメソッドを持っていることをアサートします。
  • not->toHavePrivateMethodsBesides() - クラスが指定されたプライベートメソッドのみを「許可」することをアサートします。
  • not->toHavePrivateMethods() - クラスにプライベートメソッドがないことをアサートします。
  • not->toHaveProtectedMethodsBesides() - クラスが指定されたプロテクトメソッドのみを「許可」することをアサートします。
  • not->toHaveProtectedMethods() - クラスにプロテクトメソッドがないことをアサートします。
  • not->toHavePublicMethodsBesides() - クラスが指定されたパブリックメソッドのみを「許可」することをアサートします。
  • not->toHavePublicMethods() - クラスにパブリックメソッドがないことをアサートします。
  • toUseTrait() - クラスが指定されたトレイトを使用していることをアサートします。
  • toUseTraits() - クラスが指定されたトレイトを使用していることをアサートします。

既存のすべてのアーキテクチャに関する期待事項は、アーキテクチャテストセクションで確認できます。

ティアダウンの改善

ご存知のとおり、Pestでは、afterEach()メソッドを使用して、各テスト後に特定の「ティアダウン」コールバックを実行できます。これは、テスト間のリソースのクリーンアップや状態のリセットに役立ちます。

1afterEach(function () {
2 // This will run after each test...
3});

Pest 3では、after()メソッドという新しいメソッドが導入され、describeを使用して特定のテストまたはテストグループの後で特定の「ティアダウン」コールバックを実行できるようになりました。

1it('may list todos', function () {
2 //
3})->after(function () {
4 // This will run after this test only...
5});

フックの詳細については、フックセクションを参照してください。

その他の改善点

Pest 3はPHPUnit 11をベースとしているため、Pest内でPHPUnit 11の機能をすべて使用できるようになりました。また、Pest 3には多くの軽微なバグ修正と改善も含まれています。以下はその一部です。

  • FEAT: 型カバレッジは、定数で欠落している型をチェックするようになりました。
  • FEAT: 静的クロージャがテストで使用されている場合、およびデータセットで引数が間違っている場合のエラーメッセージが改善されました。
  • FEAT: テストクロージャ内で静的解析ツールを基本的にサポートするようになりました。
  • FEAT: 期待値とAPIサーフェスの全体的な静的解析が改善されました。
  • FEAT: phpunit.xmlファイルを削除し、Pestをすぐに使用できるようにする可能性があります。
  • FIX: --fail-on-xxx CLIオプションを使用する場合、終了コードが正しく計算されていませんでした。
  • FIX: describeブロックは、メソッドをチェーンする場合、複数のメソッド呼び出しをサポートするようになりました。
  • FIX: 最初のテストの前に発生したランタイム例外がキャッチされ、表示されるようになりました。
  • FIX: 結果が100未満だが99.5より大きい場合、--min=100オプションでカバレッジレポートが失敗していました。
  • そして他にもたくさん…

今がテストに没頭し、Pestを使い始める絶好の機会です。Pest 3をすぐに使い始める準備ができている場合は、インストールガイドで手順を確認してください。現在Pest 2を使用している場合は、アップグレードガイドで詳細なアップグレード手順を確認できます。

継続的なサポートとフィードバックをありがとうございます。Pest 3で皆さんによる作品を見るのが楽しみです!


Pest 3.0の新機能について読んでいただきありがとうございます!次のプロジェクトでテストフレームワークを検討している場合は、Pestを試すべき理由を以下に示します。Pestを選ぶ理由 →