PHPUnitとは
テストコードは、他の開発者のための仕様の明文化、バグの早期発見、そしてより美しい設計を実現するための重要なツールです。これにより、開発者は安心してプロダクトコードを改善・変更することができます。ソフトウェア開発において、テストコードを書くことは品質保証の要であり、開発者としての責任でもあります。
PHPのための単体テストフレームワーク「PHPUnit」は、私たちPHPプログラマのプロダクトコードの品質を向上させるために欠かせないツールです。これはSebastian Bergmann氏によって開発され、オープンソースソフトウェア(OSS)として提供されています。PHPUnitは単体テストの作成から、テストの実行、そして結果の分析までをサポートします。
PHPUnitのリポジトリはGitHubで公開されており、誰でもそのコードを参照したり、コントリビュートしたりすることができます。PHPUnit 11は2024年2月2日にリリースされており、日々活発に開発・Issueによる議論が進められています。
PHPUnitのコードを読んでみよう
普段使用しているフレームワークやライブラリのコードを読むことは、内部挙動に対する不安を解消し、適切な設計について理解を深める絶好の機会です。数年前、内部挙動に関連するバグに直面した経験から、フレームワークの内部までしっかりと読み解くことの重要性を知りました。それ以来、コードリーディングの機会を意識的に増やし、理解を深めています。
今回は、皆さんと一緒に「日常的に使用するライブラリのコードを読み解く」というテーマに取り組みます。「どうしてここはこういう動きをするのだろう?」という疑問を抱くことは、貴重な体験です。
突然ですが、PHPUnitは、テストが成功すると「.」、失敗すると「F」(Failed)と表示されます(参考:PHPUnitのドキュメント)。
普段通りテストを回していた私はふと、「これらの記号はどのようなプロセス、どのような内部処理がされて表示されるのだろう」、と疑問に思いました。
このような小さな疑問は、コードリーディングをする重要なシグナルです。
今回はPHPUnitのコードを実際に読みながら、「.」や「F」といった記号がどのように生成され、CLIに表示されるまでの過程を探っていきます。このプロセスを通じて、OSSのコードリーディングの一例を示し、どのように読み進めていけば良いかについても触れていきます。
本記事の説明で用いるPHPUnitのバージョンは11.3.0です。
PHPUnitを動かし「.」「F」を表示させてみよう
まずは、手元でPHPUnitを動かしてみましょう。プロジェクトを作りComposerを使ってPHPUnitをインストールします。そして以下のような簡単なPHPプログラムとテストコードを書いてみます。
<?php declare(strict_types=1); namespace App; // src/Hello.php class Hello { public function hello(string $name): string { if ($name === '') { throw new \RuntimeException('Name cannot be empty.'); } return 'Hello ' . $name . '!!'; } }
<?php declare(strict_types=1); namespace AppTest; use App\Hello; use PHPUnit\Framework\TestCase; // tests/HelloTest.php class HelloTest extends TestCase { public function testHello(): void { $actual = (new Hello())->hello('asumikam'); // 成功するテスト $this->assertSame('Hello asumikam!!', $actual); } public function testException(): void { $this->expectException(\RuntimeException::class); (new Hello())->hello(''); } public function testHelloFailed(): void { $actual = (new Hello())->hello('asumikam'); // 失敗するテスト $this->assertNull($actual); } }
では、テストを実行してみましょう。
# 「tests/」ディレクトリのテストを回すコマンド $ vendor/bin/phpunit tests/ PHPUnit 11.3.0 by Sebastian Bergmann and contributors. Runtime: PHP 8.2.21 ..F 3 / 3 (100%) Time: 00:00.014, Memory: 8.00 MB There was 1 failure: 1) AppTest\HelloTest::testHelloFailed Failed asserting that 'Hello asumikam!!' is null. /my_project/tests/HelloTest.php:31 FAILURES! Tests: 3, Assertions: 3, Failures: 1.
テストコードの進捗結果である「.」「.」「F」がCLIに表示されました。