25年度入社の斎藤です。
クラスやメソッド単位での動作を保証するために行う、単体テストというものがあります。今回は、テストコードを記述することで単体テストを自動化する機能をもつPHPUnitについて、Laravelのwebアプリケーションへの導入方法と使い方を簡単に説明しようと思います。
PHPUnitの導入方法
Laravelを導入している場合、phpunitは標準でインストールされているため、特にインストール操作は必要ありません。
テストコードの作成
PHPUnitでの単体テストは、テスト対象となるクラスとテストコードを1対1の関係で作成していきます。
Laravelプロジェクトフォルダ内で以下のコマンドを打つことで tests/units 配下に単体テストファイル(Sample_Test)を作成できます。

作成できたテストファイル tests/unit/Sample_Test.php にて以下のコード変更を行います。

※テストフォルダには、単体テストファイル用フォルダのtests/unit、結合テスト用のフォルダのtests/featureが存在します。unitフォルダ内に作成されるテストファイルは、厳密な単体テスト用のファイルとして作成されるため、デフォルトではLaravelが提供する外部依存機能機能(トランザクション、ファクトリー、シーダー、ファサード認証など)が使えません。しかし、実用的には単体テストにおいても、これらのLaravelの機能を含めた単体テストを行うことがあるので、上記のコードの変更を行いました。
結果、以下のようなテストコード(Sample_Test.php)のひな型が作成できます。

Sample_Test.php
次にテスト対象として、足し算、引き算の機能を持つクラス(SampleClass.php)を作成します。

SampleClass.php
これで、テスト対象となるクラス(SampleClass.php)とテストコード(Sample_Test.php)のひな型を1対1で用意できました。最後に、テストコードを編集して、テスト対象のクラスをテストできるようにします。
テストコードファイル内で追記する主な内容は
1.テストクラス内に、テスト対象のクラスのオブジェクトを定義する
テストクラスの中で使用するテスト対象のオブジェクトを、プロパティ(変数)として宣言します。
2.setUp関数を定義する
各テストメソッドが実行される前に毎回自動で呼ばれる特別なメソッドです。
ここでテスト対象のオブジェクトを作成します。
こうすることで、テストメソッドごとに毎回新しい状態のオブジェクトを使えるようになり、テスト同士が影響し合うのを防げます。
parent::setUp()は初期化処理を継承するために必須の記述です。
3.テスト対象のメソッドごとにテストメソッドを作成する(テストメソッド名は test….)
基本的に、テスト対象のメソッド1つに対して、テストメソッドも1つ作成します。
テストメソッドごとに、テスト対象の各メソッドをテストしていくイメージです。
実際のテスト内容をここに記述します。
テストメソッド名はテスト対象のメソッド名と対応させると分かりやすいです。
4.テストメソッド内で、テスト対象クラスのオブジェクトからメソッドを呼び出し実行する
setUpメソッドで作成したテスト対象のオブジェクトを使って、実際にテストしたいメソッドを呼び出します。
5.メソッドを呼び出した後、期待する結果を検証していく(assertion)
期待する結果と実際の結果が一致しているかを検証する手段として、assertion(アサーション)が用意されています。
具体例として
・予測値と実際の結果を比較するメソッド : assertEquals()
・trueかどうかを検証するメソッド : assertTrue()
・配列の数を検証するメソッド : assertCount()
などがあります。
これをテストメソッド内で利用していきます。
これら1~5の内容をテストコード(Sample_Test.php)に追加すると以下のようになります。

あとはテストコードを実行するだけでテストを行えます。
テスト実行コマンドは以下の通りです。
作成した全てのテストファイルを実行する場合

特定のテストファイルを実行する場合

テストコードを実行すると以下のような結果が得られます。
今回の二つのメソッド(add、sub)は想定通りに機能していることが確認できました。

最後に
PHPUnitを学んで率直に感じたことは、テストコードを記述していくことはかなり労力がかかる作業であるということです。テスト対象のコードとテストコードを対にして記述していく必要があるため、単純計算で2倍程度のコードを記述することになります。小規模なシステムや修正があまり発生しないコードでは、この労力は割に合わないかもしれません。しかし、システムが大規模になり、複数人での開発や頻繁な変更が発生する環境では、自動テストによって迅速に品質を保証し続けられるメリットは大きいものなのだろうと思いました。
以上で今回の話をおわります。
ありがとうございました。
