PHPは何の略称だったかを考え出して無限のドツボにハマってしまった umiushi です。
主に社内向けの内容を書き連ねます。
はじめに
この記事は Windows7 Professional x64 の環境にもとづいて記述されている。
別の環境( Mac とか Linux とか)の場合は手順が異なる可能性があるので注意。
前提条件
- PHP 5.6 以上がインストール済みであり、PATH が適切に設定されていること。
コマンドプロンプトで下記のコマンドを入力し、PHP のバージョンが表示されればインストール済み。
php --version
そうでない場合は PHP をインストールし、環境変数の PATH に php.exe のあるディレクトリを追加する。
PHPUnit のインストール
公式サイトから直接ダウンロードする場合
PHPUnit の公式サイトから phpunit-*.phar をダウンロードする。
ダウンロードした phpunit-*.phar を開発用のディレクトリのルートに置き、phpunit.phar に名前を変更する(バージョン番号を消す)。
phpunit.phar をおいたディレクトリに移動し、
php phpunit.phar --version
と入力して PHPUnit のバージョンが表示されればOK。
Composer を利用する場合
Composer を使うことでもインストールできる(PHP で開発するときは便利なのでできる限り導入するといいぞ)。
開発用ディレクトリに composer.json を設置し、次のように記入する。
{
"require-dev": {
"phpunit/phpunit": "*"
}
}
次にコマンドプロンプトを開き、
composer update
と入力する。
すると composer.lock ファイルと vendor ディレクトリが生成される。
Composer の処理が完了すれば、コマンドラインで
vendor\bin\phpunit --version
と入力することで PHPUnit を実行できる。
Composer を使用してインストールした場合は、テストケースを記入するファイルの先頭に
require_once("vendor/autoload.php");
と記入する。
テストケースを作成する
ここからは Composer を使用したパターンで記述する。
開発用ディレクトリに src ディレクトリと test ディレクトリを作成する。
src には実際のソースファイルを、test にはテストケースを記入したファイルを入れるようにする。
まず composer.json を次のように変更する。
{
"require-dev": {
"phpunit/phpunit": "*"
},
"autoload": {
"psr-4": {
"Sample\\": "src/"
}
}
}
ここで "Sample\\" の部分はプロジェクトに合わせて適当に変更すること。
composer.json を変更した場合は、composer update を実行する必要があるが、今回は "autoload" の変更のみであるため、composer dumpautoload のみでよい。
コマンドプロンプトを開き、次のように入力する。
composer dumpautoload
これで vendor\autoload.php が更新される。
次にテスト対象となるクラスを用意する。
今回は src\Sample.php というファイルを作成し、次のように記述する。
<?php
namespace Sample;
class Sample {
// $a + $b を返す
public function Add($a, $b) {
return $a + $b;
}
// $a - $b を返す
public function Sub($a, $b) {
return $a + $b;
}
}
加算と減算を行うだけの単純なクラスであるが、Sub メソッドには不具合があり、減算を返すつもりが加算結果を返すようになっている(コピペすると発生しやすいはず)。
テスト対象が完成したらテストケースを作成する。
test ディレクトリに SampleTest.php ファイルを作成し、次のように記入する。
<?php
require_once('vendor/autoload.php');
class SampleTest extends PHPUnit\Framework\TestCase {
public function test_add() {
$sample = new Sample\Sample();
$this->assertEquals(10, $sample->Add(4, 6));
}
public function test_sub() {
$sample = new Sample\Sample();
$this->assertEquals(1, $sample->Sub(7, 6));
}
}
このテストケースでは、Sample::Add メソッドと Sample::Sub メソッドが正しく意図したとおりに動作しているかをテストする。
テストケースとして認識させるためには、PHPUnit_Framework_TestCase クラスを継承し、test から始まる public なメソッドを作成する。
もしテストケースのメソッド名を test から始めたくない場合は、
/**
* @test
*/
public function foo() {
...
}
のように @test アノテーションを付与する。
テストを実行する
ここまでできたら、いよいよテストを実行する。
コマンドプロンプトを開き次のように入力する。
vendor\bin\phpunit test\
これで test ディレクトリ内のファイルをテストケースとしてテストが実行される。
今回は Sample::Sub メソッドに不具合があるため
.F 2 / 2 (100%)
のように2番目のテストで失敗した、と表示される。
テストケースのリファクタリング
今回作成したテストケースでは、各テストケースごとに
$sample = new Sample\Sample();
を呼び出している。
今回はコンストラクタに引数を取らないクラスでテストを行ったが、これが長ったらしい引数を取るような場合だといささか面倒である。
そこで setUp メソッドを定義して各テストケースの実行前に自動的に実行されるようにする。
SampleTest クラスを次のように変更する。
class SampleTest extends PHPUnit\Framework\TestCase {
protected $sample;
protected function setUp() {
$this->sample = new Sample\Sample();
}
public function test_add() {
$this->assertEquals(10, $this->sample->Add(4, 6));
}
public function test_sub() {
$this->assertEquals(1, $this->sample->Sub(7, 6));
}
}
このようにすることで各テストケースごとに自動的に行われる初期化処理を記述することができる。
おわりに
上記の内容を継続的にかつ効果的に使用することで、品質の良いプロダクトコードを書くことができる。
テストはいいぞ。