PHPUnit の使い方
PHP_CodeSniffer や PHPStan などで、コードの文法的な正しさは確認できますが、 そのコードが本当に正しい動作を行っているかどうかを確認するためには、やはり最終的には動作させてみるしかありません。
PHPUnit とは?
PHPUnit は、PHP のテストフレームワークです。 その名前からわかる通り、基本的には単体テスト(UnitTest)に使用するためのものです。 プログラムというのは、分割統治法によるアプローチによって、小さく小さく分割され、その分割されたものが統合されることで、最終的に1つのアプリケーションとして機能しています。 単体テストとは、その小さく小さく分割されたその1つ1つをテストするという意味です。 PHP で言えばそれは、1つ1つのクラス、1つ1つのメソッドをテストするということです。
PHPUnit のインストール
さっそくですがインストールしていきましょう。
Composer でインストールする
PHPUnit をインストールする方法はいろいろありますが、Composer を使っている場合は Composer を使ってインストールするのが楽だと思います。
Composer を使って PHPUnit をインストールするには、下記のコマンドを実行するだけです。
基本的には開発環境で使うツールだと思うので、--dev オプションを付けておきましょう。
Composer の使い方がわからないという方は、まずは「Composer の使い方(その1:概要)」を参考にしてください。
php composer.phar require --dev "phpunit/phpunit"
インストールできたか確認する
PHPUnit をインストールすると、phpunit コマンドが使えるようになっていますので、使用できるか確認してみましょう。
実行ファイルは ".\vendor\bin\" ディレクトリにあります。
.\vendor\bin\phpunit -h
注意:XAMPP を使用している方へ
XAMPP にはデフォルトで古いバージョンの PHPUnit が含まれていて、しかも PATH が通った状態になっています。 そのため、コマンド名だけで実行すると、XAMPP に入っている方の古い PHPUnit が動きますので注意してください。 Composer でインストールした方の PHPUnit を動かすには ".\vendor\bin" が必要です。
# XAMPP の場合、phpunit とだけ入力すると、"C:\xampp\php\phpunit.bat" が動くので注意 phpunit -h
テストの書き方
テストを書くにはいくつかルールがあります。
Hogeという名前のクラスのテストは、HogeTestという名前のクラス(テストクラス)に記述します。- テストクラスは、
PHPUnit\Framework\TestCaseを継承します。 -
テストの内容は、
testから始まる名前のpublicメソッド(テストメソッド)に記述します。
※ あるいは、@testアノテーションをメソッドのコメント部で使用します。 -
テストメソッドの中で
assertSame()のようなアサーションメソッドを使用して、期待される値と実際の値が等しいことを確かめます。
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class HogeTest extends TestCase
{
public function testHogeHoge(): void
{
$stack = [];
$this->assertSame(0, count($stack));
}
}
アサーションメソッド
アサーションメソッドとは、テストしたいことが、正しいかどうかを判定するためのメソッドです。
テストメソッドの中で、アサーションメソッドを呼び出していく形で、テストを作成します。
アサーションメソッドのメソッド名は全て assert から始まります。
どんなメソッドがあるかは、ここでは記載しません。 あまりにも大量にありますので、公式のドキュメントを見てもらった方が良いと思います。
Expected と Actual
setUp() と tearDown()
各テストメソッドが呼ばれる際、その前処理と後処理を共通化したい場合、PHPUnit では setUp() と tearDown() というメソッドが用意されています。
このメソッドと同じ名前のメソッドをテストクラスに定義すると、各テストメソッドが呼ばれる際に自動的に呼んでくれます。
setUp() が前処理、tearDown() が後処理です。
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class HogeTest extends TestCase
{
public function setUp(): void
{
// 前処理
}
public function testHogeHoge(): void
{
$stack = [];
$this->assertSame(0, count($stack));
}
public function tearDown(): void
{
// 後処理
}
}
基本的な使い方
さっそく使ってみましょう。
単一のファイルを実行する
1つのファイルを実行する場合は、実行したいファイル名を指定します。 指定できるのは1つだけです。
.\vendor\bin\phpunit .\tests\HogeTest.php
複数のファイルを実行する
複数のファイルを実行する場合は、実行したいディレクトリ名を指定します。 指定できるのは1つだけです。
.\vendor\bin\phpunit .\tests
出力内容に色を付ける
デフォルトでは出力内容には色が付いていないので白黒な画面になってしまうと思われますが、この出力内容に色を付けることができます。
色を付けるには --colors オプションを付けます。
--colors オプションで指定できる値は下記の3つです。
-
never:出力を色分けしません。これは、--colorsオプション自体が未指定の場合のデフォルトです。 -
auto:ターミナルが色をサポートしていない場合や、出力をコマンドにパイプしたりファイルにリダイレクトしたりする場合を除き、出力に色を使います。--colorsオプションでだけを指定して、値を何も指定しなかった場合は、autoを指定していることと同じになります。 -
always:ターミナルが色をサポートしていない場合や、 出力をコマンドにパイプしたりファイルにリダイレクトしたりする場合も含めて、常に出力に色を使います。
# 値を省略した場合は --colors=auto と同じ .\vendor\bin\phpunit --colors .\tests
PHPUnit 9.5.9 by Sebastian Bergmann and contributors.
.. 2 / 2 (100%)
Time: 00:00.012, Memory: 4.00 MB
OK (2 tests, 10 assertions)
エラーが発生した時点で停止させる
デフォルトでは、どこかのテストでエラーが発生しても、全てのテストの実行が終了するまで止まりません。 どこかのテストでエラーが発生するということは、それを使っている他の個所もまたエラーになるということです。 エラーが1つでも見つかったのなら、すぐにその時点で実行を止めて、エラーの個所を教えて欲しいと感じるでしょう。 全てのテストが終わるまで待っているのは、かなりの時間のロスになります。
注意しないといけないのは、最初に発生したエラーの発生個所がエラーの本当の原因ではない可能性があるということです。 あくまでテストの実行順的に最初に発生したというだけなので、エラーの本当の原因はさらに別の個所で発生したエラーである、という可能性があります。
エラーが発生した時点で停止させるには、--stop-on-failure オプションを使用します。
.\vendor\bin\phpunit --stop-on-failure .\tests
ブートストラップ用の PHP ファイルを指定する
CakePHP や Laravel などの PHP フレームワークを使用しているアプリケーションのコードを PHPUnit でテストしたいとしましょう。 フレームワークは、アプリケーションの実行に必要な様々な処理を、初期化処理として自動的に行ってくれています。 言い換えれば、そのアプリケーションのコードは、単体では正しく動作しないということです。 フレームワークと組み合わせて初めて正しく動作するのです。
そのような何かに依存したコードを PHPUnit 上で動かすためには、その依存しているものが行っている前処理と同じ処理を、テストの前に実行しておく必要があります。
PHPUnit のテストの前に実行される処理は、PHP ファイルで、--bootstrap オプションで指定できます。
.\vendor\bin\phpunit --bootstrap=.\tests\bootstrap.php .\tests
XML設定ファイル
PHPUnit では、コマンドのパラメーターだけでも細かな設定ができるのですが、さすがに全てを指定するのは大変です。 コマンドよりも設定ファイルを使用した方が良いでしょう。
設定ファイルを使用する
設定ファイルを使用する方法は2つあります。
--configuration オプションで指定する
1つ目の方法は、--configuration オプションで使用したい設定ファイルを指定することです。
複数の設定ファイルを使用して、設定を切り替えたい場合などには便利かもしれません。
--configuration オプション には、エイリアス(別名) -c オプションがあります。
.\vendor\bin\phpunit -c .\custom_phpunit.xml
デフォルトの設定ファイルを使用する
2つ目の方法は --configuration オプションは指定せず、デフォルトの設定ファイルを使用する方法です。
--configuration オプションを指定しない場合(つまりデフォルト)、
PHPUnit は現在のディレクトリから設定ファイルを探します。
この時に探されるファイルの名前は、「phpunit.xml」「phpunit.xml.dist」の2つです。
この2つのファイル名のどちらかと一致するファイルが見つかった場合に、そのファイルが自動的に読み込まれます。
もし複数のファイルが見つかった場合は、前述の順番で優先的に読み込まれます。
.\vendor\bin\phpunit
設定ファイルのフォーマット
設定ファイルのフォーマットは XML です。
phpunit タグをルートとし、その中に設定内容のタグを記述していきます。
XMLなのでコメントも書けます。
どんな設定項目があるかは、ここでは記載しません。 あまりにも大量にありますので、公式のドキュメントを見てもらった方が良いと思います。
ここでは簡単な例だけ記載しておきます。
<?xml version="1.0" encoding="UTF-8"?> <phpunit colors="true"> <testsuites> <testsuite name="all"> <directory>tests</directory> </testsuite> </testsuites> </phpunit>
テストスイート
複数のファイルをテストの対象として指定する方法として、ディレクトリを指定する方法がありました。 しかし、これだとそのディレクトリの全てのテストを毎回実行することになってしまいます。 必ず通るとわかっているテストを毎回実行していては、作業効率があまりよろしくありません。 テストしたい個所とあまり関係がない個所のテストはスキップしたいと考えるでしょう。
PHPUnit では、どのテストをどの順番で実行するかを細かく指定することができます。 その際に使用するのがテストスイートです。
テストスイートを定義する
テストスイートを定義するには、設定ファイル内で、testsuites タグの中に、testsuite タグで定義していきます。
testsuite タグの name 属性でテストスイートの名前を指定できます。
この名前は、テストスイートを実行する際に使用する名前になります。
ファイルを指定する場合は、file タグを使用し、ディレクトリを指定する場合は、directory タグを使用します。
<?xml version="1.0" encoding="UTF-8"?> <phpunit colors="true"> <testsuites> <!-- 全てのモデル --> <testsuite name="model"> <directory>tests/TestCase/Model</directory> </testsuite> <!-- お金関係のみ --> <testsuite name="money"> <file>tests/TestCase/Model/MoneyTest.php</file> <file>tests/TestCase/Model/CurrencyTest.php</file> <directory>tests/TestCase/Controller/Payments</directory> </testsuite> </testsuites> </phpunit>
テストスイートの一覧を表示する
定義したテストスイートの一覧は設定ファイルを見てもわかりますが、--list-suits オプションを使用すると一覧表示してくれます。
.\vendor\bin\phpunit --list-suites
PHPUnit 9.5.9 by Sebastian Bergmann and contributors. Available test suite(s): - model - money
テストスイートを実行する
定義したテストスイートを実行するには、--testsuite オプションで、実行したいテストスイートの名前を指定します。
ちなみに、--testsuite オプションを使用しない場合は、定義している全てのテストスイートが実行されます。
複数のテストスイートで重複しているテストがある場合、そのテストは1度だけ実行されますので、重複は気にしなくても良いでしょう。
.\vendor\bin\phpunit --testsuite money
グループ
テストスイートでファイルやディレクトリの単位でテスト対象を定義できましたが、 PHPUnit では、さらにもっと細かく、クラスやメソッド単位でテスト対象をグループ化する方法があります。
例えば、バグ管理システム(課題管理システム)のチケット番号を元にテストをグループ化することで、そのバグ(課題)に関するテストだけ実行するといったような使い方ができます。
グループを定義する
グループはアノテーションとして定義します。
アノテーションというのは、PHP のドキュメンテーションコメントに @アノテーション名 引数 形式でコメントを書くことで、メタデータを定義するものです。
PHPDoc などで @param や、@return などが良く使われているので、見慣れているのはないでしょうか。
グループを定義するには、PHP のメソッドやクラスのドキュメンテーションコメントに @group グループ名 の形式で記載するだけです。
簡単に定義できるからと言って、むやみやたらにグループを作っていると、あっという間に管理できなくなるので注意しましょう。
グループのアノテーションは @group の他にも、@author 、@ticket などがあります。
これらは、@group のエイリアス(別名)ですので、@group と同じように使用できます。
<?php
use PHPUnit\Framework\TestCase;
/**
* @group my
*/
class MyTest extends TestCase
{
/**
* @group regresssion
* @group bug2204
*/
public function testSomething()
{
}
/**
* @author hogehoge
* @ticket #1234
*/
public function testSomethingElse()
{
}
}
グループの一覧を表示する
定義したグループの一覧を表示するには、--list-groups オプションを使用します。
.\vendor\bin\phpunit --list-groups
PHPUnit 9.5.9 by Sebastian Bergmann and contributors. Available test group(s): - #1234 - bug2204 - default - hogehoge - my - regresssion
グループを実行する
定義したグループを実行するには、--group オプションで、実行したいグループの名前を指定します。
.\vendor\bin\phpunit --group bug2204
コードカバレッジ解析
PHPUnit でテストを実行したときに、テスト対象のコードのうちどれくらいの割合がテストされたかというのが分かります。
PHPUnit のコードカバレッジ解析を使用するためには、別途 Xdebug のインストールが必要です。 Xdebug のインストール方法と設定方法はここでは記載しません。 「Xdebug の使い方」を参考にしてください。
テスト対象のコードを指定する
コードカバレッジを出力するには、まずテスト対象のコードがどこにあるか指定する必要があります。 テストコードの場所ではなく、実際のソースコードの場所です。 指定する方法は2つあります。
--coverage-filter オプションで指定する
1つ目の方法は、--coverage-filter オプションで指定することです。
.\vendor\bin\phpunit --coverage-filter .\src
設定ファイルで指定する
2つ目の方法は、設定ファイルで coverage タグで指定する方法です。
<?xml version="1.0" encoding="UTF-8"?> <phpunit colors="true"> <testsuites> <testsuite name="all"> <directory>tests</directory> </testsuite> </testsuites> <coverage> <include> <directory>src</directory> </include> </coverage> </phpunit>
カバレッジレポートをHTMLで出力する
カバレッジレポートをHTMLで出力するには、--coverage-html オプションで出力先ディレクトリを指定します。
指定したディレクトリの中に、カバレッジレポートがHTMLファイルとして出力されます。
HTMLで出力する --coverage-html オプションの他にも、テキストとして出力する --coverage-text オプションや、XMLファイルとして出力する --coverage-xml オプションなどもあります。
.\vendor\bin\phpunit --coverage-html coverage
Composer スクリプトとして登録する
設定ファイルがあるとはいえ、コマンドを毎回入力するのは面倒に感じてくると思います。 特に、ここまでの説明で散々繰り返し記載してきた ".\vendor\bin" を記述するのが面倒に感じてくると思います。 そこで、コマンドを Composer スクリプトとして登録しておくと、入力の手間が少なくなって便利です。 Composer スクリプトでは、 ".\vendor\bin" に PATH が通っているので、".\vendor\bin" を入力する必要はありません。 Composer スクリプトの使い方がわからないという方は、「Composer の使い方(その2:スクリプト)」を参考にしてください。
{
"name": "hoge/hoge",
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"scripts": {
"test": "phpunit"
}
}
php composer.phar test
色がちゃんとつかない場合
Composer スクリプトから実行した場合に出力内容に色を付ける場合、--colors オプションを付けていても、色がちゃんとつかない場合があります。
設定ファイルで colors="true" を指定しても色がちゃんと付きません。
そもそも設定ファイルの colors 属性は xs:boolean 型なので、true か false のどちらかしか指定できません。
その場合は、--colors オプションの値に always を指定してみましょう。
{
"name": "hoge/hoge",
"require-dev": {
"phpunit/phpunit": "^9.5"
},
"scripts": {
"test": "phpunit --colors=always"
}
}
参考サイト
- PHPUnit – The PHP Testing Framework
- 1. PHPUnit のインストール — PHPUnit latest Manual
- 3. コマンドラインのテストランナー — PHPUnit latest Manual
- 5. テストの構成 — PHPUnit latest Manual
- 1. アサーション — PHPUnit latest Manual
- 2. アノテーション — PHPUnit latest Manual
- 3. XML 設定ファイル — PHPUnit latest Manual
- 3. The XML Configuration File — PHPUnit 9.5 Manual
