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)); } }
このようにすることで各テストケースごとに自動的に行われる初期化処理を記述することができる。
おわりに
上記の内容を継続的にかつ効果的に使用することで、品質の良いプロダクトコードを書くことができる。
テストはいいぞ。