https://d226lax1qjow5r.cloudfront.net/blog/blogposts/converting-your-test-suite-to-pest/shifting-to-pest.png

テスト・スイートをPESTに変換する

最終更新日 December 16, 2021

所要時間:4 分

テスト駆動開発によってコードの書き方を変えたことで、率直に言って、プログラマーとしての能力が変わりました。突然、自信を持ってサービスや機能を書けるようになった。 いまだに「長い間、「テストをする時間がない、 PHPUnitは、TDD PHP を書くときのデファクト・ツールです。

それを変えるかもしれない新しいプロジェクトが最近登場した。そこには 良い文書そして ミートアップコミュニティがあり、開発者にとって魅力的な選択肢であることを示している。私はもちろんPESTについて言及している。 Vonage PHP SDK.

現在のスイートルーム

私たちの Vonage PHP SDK は長年にわたって包括的に保守されてきたため、完全なテスト・スイートが含まれています。その範囲は「エンタープライズ・レベル」ではありませんが、それでもPESTをテストするには有用な演習です。

このブランチの このブランチには、4039 個のアサーションを実行する 831 個のテストがあります。スキップされたテストが 9 個、不完全なテストが 15 個あります。PHP8 での総実行時間は 13:54 です。

Screenshot of total tests showing 9 skipped and 15 incomplete tests.Screenshot of total tests showing 9 skipped and 15 incomplete tests.

ちなみに、このテストはかなりまともに実行されるし、そのうちのひとつはタイムアウトのテストである。ここでの目的はランナーを改善することではなく、ランナーを変更して何が起こるかを見ることだ。最初にやることは PESTをインストールしてをインストールして実行することである。PEST の最も重要な特徴のひとつは、次のとおりです。 PHPUnit との完全な後方互換性があること。との完全な後方互換性があり、使用している構文にかかわらず互換性を保ったまま使用できることです。このため、PEST をインストールして実行し、その結果を確認することができます。 並列テスト機能を実装してみることができます。

PESTをインストールするには、コマンドラインで以下を実行する:

composer require pestphp/pest

composerコマンドを1つ実行するだけで、PESTを実行することができる。しかし、PESTが実行されるリポジトリには、すでに必要な要件があり、そのひとつがPHPの最低バージョン7.3である。PESTはすでにPHPの最低必要バージョンが7.3以上になっているので、最新版にするために手を加える必要はない。

PESTを実行し、何が起こるか見てみよう:

./vendor/bin/pest

まず最初に気がつくのは、PEST が PHPUnit の出力書式として --testdox引数を使用して PHPUnit の出力をフォーマットしていることです。この出力は、なかなかすばらしいものです:

Test screenshot, showing a time of 13.21 seconds.Test screenshot, showing a time of 13.21 seconds.

うーん、13秒28か。ランナーだけならもっと速い。PESTのパラレル機能を使ってみたらどうだろう?これは別のパッケージとして提供されている:

composer require pestphp/pest-plugin-parallel

そして今度はそれを実行する:

./vendor/bin/pest -parallel

そして...ああ。どうやら運が尽きたようだ:

Screenshot of a PHP bug.Screenshot of a PHP bug.

ググってみたところ、PHPUnit の issue log に PHP 自体にバグがあることがわかりました:

https://github.com/sebastianbergmann/phpunit/issues/4305

それが、私たちが最先端であることの代償なのだろう。

Photo of frustrated person looking at their laptop screen.Photo of frustrated person looking at their laptop screen.

PHPUnitの構文とPESTの比較

テストランナーで遊んでいるが、実際にコードを見せたり、PESTの実際の目的を説明していない。

Laravelコアメンバー ヌーノ・マドロの構文をモデルにした新しいフレームワークとしてPESTを作成しました。 JestJavascriptフレームワークの構文をモデルにした新しいフレームワークです。これは、PHP(そして特にLaravel)が、Javascriptの記述方法に似た、よりクロージャベースの関数型構文に移行している現在のトレンドに非常にマッチしています。フルスタックWebアプリケーションのPHPバックエンドテストをフロントエンドテストと同じような構文で書くことは、論理的に理にかなっています。以下は、Vonage PHP SDK の「テスト前とテスト後」の例です:

class NumberTest extends VonageTestCase  
{  

 /**  
 * @var Number;  
 */
 protected $number;  
  
 public function setUp(): void  
 {  
	$this->number = new Number('14843331212');  
 }  
 
 public function testNumberConstructor(): void  
 {   
	$this->assertEquals('14843331212', $this->number->getNumber());  
 }

ここでは、いくつかのよくあるパターンを使っている。 setUp()を使っています。 assertEquals()を使用します。 TestCaseのヘルパークラスを使用します (この例では VonageTestCaseを使用します (この例では、PHPUnit のヘルパークラスを継承しています)。

さて、同じテストをPEST構文で書いてお見せしよう:

use Vonage\Numbers\Number;  
  
beforeEach(function () {  
   $this->number = new Number();  
});  
  
test('number constructor', function () {  
   expect($this->number->getNumber())->toEqual('14843331212');  
});

PESTの構文はJESTに非常に似ている。また、PESTのコアバリューの1つである、APIでより流動的なメソッドチェイニングを行い、より少ないコードしか書かないという、非常にLaravel的な哲学に基づいたアプローチも示しています。我々は今、より高次の beforeEach()そして、PHPUnit の古典的な PHP 関数構造が、より関数的な構文に置き換わりました。この例では 期待値 APIがどのようにアサーションを連鎖させるのかを示しています。 expect(true)->toBe(value)あるいは expect($variable)->toBeArray().

では、オートメーションは?

正直に言うと、これは私が望んだようにはいかなかった。しかし、その理由をお見せしよう。

ツイッターで知った ツイッターを見ていて、PHPUnitスイートを自動的にPESTに変換するツールを使えば、コードがLaravelであるかどうかに関係なく、PESTに変換できる可能性があることに気づきました。そこで ペストコンバータに向かいました。 リポジトリとブランチをセットアップして試してみました。実行すると、Shiftは指定したベースブランチから新しいブランチを作成し、論理的なステップコミットを作成して構文を移動します。最初にやらなければならないことのひとつは test/フォルダを tests/に変更し、コンバーターがテストの場所を認識できるようにすることです。

しかし、変換後にPESTを実行すると:

Screenshot showing PestxceptionsestCaseClarrOrTrailNotFound.Screenshot showing Pest\Exceptions\TestCaseClarrOrTrailNotFound.

うーん。順風満帆というわけではないんだね。特筆すべきは、いくつかの理由で何が起こるか見当がつかなかったことだ:

  • Vonage PHP SDK はフレームワークを選びません。

  • それは Prophesizeライブラリ

  • 多くの PHP 特性を使用しているため、テストスイートは若干複雑になっています。

伝統的なコンポジションではなく、PESTはコンポジションに異なるパターンを採用している。PESTには pest.phpのようなヘルパー関数、特性、一般的なメソッドを指定できる設定ファイルがあります。 RefreshDatabase.また、クラスをどのフォルダに適用させたいかをこのように指定することもできる:

uses(\VonageTest\HTTPTestTrait::class)->in('Secrets');

PESTコンバーターがこれらを解決できない理由は、多くのエッジケースにあります。Laravel Shiftの Jason McCrearyによって指摘されたことです。 $this->appこれはLaravelのアプリケーションインフラストラクチャとコンフリクトします(Laravelアプリがあるかどうかわからないため)。

結論

PESTコンバーターがテストを自動化するのは難しいが、2つの結論が導き出された:

  • ペストコンバーターの開発者であるLaravel Shiftは、私が使用したライブラリのエッジケースをすでに調べており、その処理方法に取り組んでいます。

  • テスト・スイートが複雑だったり、過剰に設計されていたりする場合は、コンバーターを実行しないでください。

どんなことでもそうだが、自動化によって大規模なリファクタリングを行うことにはリスクがある。私たちの場合、フレームワークのない生のPHPライブラリを扱っていることがリスクとなった。しかし、Shiftはターゲットブランチを経由して更新を行い、そこからShiftブランチを作成することで、リスクを最小限に抑えます。実行できない場合は、マージしないでください!また ヒューマンシフトサービスを使うという選択肢もあります。

もしあなたがSymfonyやLaravelのアプリを持っているなら、このコンバーターはこれらのケースを念頭において設計されているので、Shiftはかなり堅固なものになるでしょう。

PESTを採用すべきか?いつものように、それはあなた次第です。もしあなたがPHPで変化している物事の最先端を維持したいのであれば、これは確かに魅力的なオプションです。しかし、PESTのシンタックス構造は、APIフローに対するLaravelのアプローチと一致しているため、Symfony、CakePHP、Drupalのような他の一般的なものを使用している場合、開発者を混乱させる可能性があることを覚えておいてください。

シェア:

https://a.storyblok.com/f/270183/400x385/12b3020c69/james-seconde.png
James SecondeシニアPHPデベロッパー

スタンダップ・コメディーの学位論文を持つ俳優の訓練を受け、ミートアップ・シーンを経てPHP開発に携わるようになった。技術について話したり書いたり、レコード・コレクションから変わったレコードを再生したり買ったりしています。