PHPUnitは、オブジェクトのテストにだけ使えるのかと思っていましたが、単純な関数の単体テストでも有効なんですね。(ドキュメントのサンプルは、関数のテストが載ってますが)
とういわけで、PHPUnitの単純な使い方を紹介します。
PHPUnitの使い方を参考にしました。(というかそのまんまです。すみません。というか、ありがとうございます。)
■1. 何をテストするか?
スクリプトにアクセスしたユーザのログをファイルに記録する関数をテストすることにします。
bool loginLogWriter(string user)
userを引数にとり、ファイルに、user、アクセス日時を書き込みます。
user、アクセス日時は、1回のアクセスに付き、1行をファイルの最後にタブ区切りで追記します。
書き込みが正常に終了した場合に、trueを返します。失敗した場合は、falseを返します。
何をテストするかを考えていくときりがありませんが、
タブ区切り、ファイル書込ということで、次の項目をテストすることにします。
■2. テストのスケルトンの作成
まず、始めに(テストする関数を作る前に)、スケルトンを作ります。
test.php
// run Test Suites
$suite = new PHPUnit_TestSuite("loginLogWriterTest"); //←テストするクラス名(1)
$result = new PHPUnit_GUI_HTML($suite);
$result->show();
?>
test/loginLogWriterTest.php
class loginLogWriterTest extends PHPUnit_TestCase { //←(1)のテストするクラス名
function loginLogWriterTest($name) //←コンストラクタ
{
$this->PHPUnit_TestCase($name);
}
function setUp()
{
}
function tearDown()
{
}
function testSetup() //←testで始まるメソッドがテストとして実行されます。
{
$this->fail("no implementation"); //←assertのメソッドについては、PHPUnit_Assertを参照
}
}
?>
loginLogWriter.php
ここまでで、とりあえず、test.phpを実行してみます。
(un)check all にチェックをつけて、run testsをクリックします。
failメソッドで、強制的に失敗させていますので、失敗していれば(橙色になっていれば)成功です。
■3. テストの作成
関数を作成する前に、まず、テストを作成します。
「1. 引数で渡されたuserが正しく記録されていること。」から作ります。
test/loginLogWriterTest.php
class loginLogWriterTest extends PHPUnit_TestCase {
var $logFile;
function loginLogWriterTest($name)
{
$this->PHPUnit_TestCase($name);
}
function setUp() //←テストの前に呼び出されます
{
$this->logFile = "/tmp/test_log.log";
if ( !file_exists($this->logFile) ) {
touch($this->logFile); //←ログを書き出すファイルを生成しています
}
}
function tearDown() //←テストの終了後に呼び出されます
{
unlink($this->logFile); //←生成したファイルを削除しています
}
function testWriteLog() //←testで始まるメソッドがテストとなります
{
$user = "hoge";
$regexp = "|^".date("Y/m/d")."\t".date("H:i:").".*".$user."\t\n$|";
loginLogWriter($user);
$out = file($this->logFile); //←ファイルの内容を配列に取り出します
$this->assertRegExp($regexp, $out[count($out)-1]); //←正規表現を使って出力結果をチェックします
}
}
?>
ここまでで、テストを実行します。
まだ、loginLogWriter()を作成していないので、エラーになります。
■4. 関数の作成
まず、関数の定義だけを記述します。
loginLogWriter.php
テストを実行します。
まだ、処理を書いていないので、エラーになりました。
テストスクリプトのエラーも出ていますが、気にしないでおきましょう。
さて、いよいよ、実際の処理を作ります。
loginLogWriter.php
テストを実行します。
■5. 次のテストです。
「2. userにタブが含まれていても正しく記録されること。」
同様に、テストを作ります。
test/loginLogWriterTest.php
class loginLogWriterTest extends PHPUnit_TestCase {
var $logFile;
function loginLogWriterTest($name)
{
$this->PHPUnit_TestCase($name);
}
function setUp()
{
$this->logFile = "/tmp/test_log.log";
if ( !file_exists($this->logFile) ) {
touch($this->logFile);
}
}
function tearDown()
{
unlink($this->logFile);
}
function testWriteLog()
{
$user = "hoge";
$regexp = "|^".date("Y/m/d")."\t".date("H:i:").".*".$user."\t\n$|";
loginLogWriter($user);
$out = file($this->logFile);
$this->assertRegExp($regexp, $out[count($out)-1]);
}
function testReplaceTab() //←追加したテストです
{
$user = "hoge\thoge";
$repUser = str_replace("\t", " ", $user); //←タブを空白2個に置換します
$regexp = "|^".date("Y/m/d")."\t".date("H:i:").".*".$repUser."\t\n$|";
loginLogWriter($user);
$out = file($this->logFile);
$this->assertRegExp($regexp, $out[count($out)-1]);
}
}
?>
テストを実行します。
エラーになります。
次に、関数の処理を修正します。
loginLogWriter.php
テストします。
緑色のバーになれば、テスト完了です。
■6. 最後のテストです
「3. 書き込むファイルが存在しない場合にfalseを返すこと。」
同じ手順です。
テストを作ります。
test/loginLogWriterTest.php
class loginLogWriterTest extends PHPUnit_TestCase {
var $logFile;
function loginLogWriterTest($name)
{
$this->PHPUnit_TestCase($name);
}
function setUp()
{
$this->logFile = "/tmp/test_log.log";
if ( !file_exists($this->logFile) ) {
touch($this->logFile);
}
}
function tearDown()
{
unlink($this->logFile);
}
function testWriteLog()
{
$user = "hoge";
$regexp = "|^".date("Y/m/d")."\t".date("H:i:").".*".$user."\t\n$|";
loginLogWriter($user);
$out = file($this->logFile);
$this->assertRegExp($regexp, $out[count($out)-1]);
}
function testReplaceTab()
{
$user = "hoge\thoge";
$repUser = str_replace("\t", " ", $user);
$regexp = "|^".date("Y/m/d")."\t".date("H:i:").".*".$repUser."\t\n$|";
loginLogWriter($user);
$out = file($this->logFile);
$this->assertRegExp($regexp, $out[count($out)-1]);
}
function testFileExists() //←追加しました
{
unlink($this->logFile);
$user = "hoge";
$this->assertFalse(loginLogWriter($user));
}
}
?>
テストを実行します。
テストが失敗することを期待したのですが、緑色のバーになり成功しました。
確認のために、関数に戻り値trueを入れてみます。
loginLogWriter.php
テストします。
橙色になり、失敗しました。関数は、正常に実行されているようです。
ログを書き込むファイルを削除したはずなのに、と考えていると思い出しました。
fopenは、オープンするファイルがない場合には、ファイルを作成します。
テストが失敗の状態ですので、関数の処理を修正して、テストが成功することを確認します。
loginLogWriter.php
テストを実行します。今度は成功しました。
このように、テストの作成→テストの失敗の確認→処理の作成→テストの成功の確認 を何度も繰り返して、プログラムを作成していけばいいのではないでしょうか。
開発用に持ち歩いているノートに、PHPをインストールした。
正確には、1年前にインストールしていた、4.3.3を4.3.9にアップデートした。
1年前は、問題なくインストールできたはずなのに、うまくいかない。
結局、php4ts.dllをC:\Windows\System32にコピーして解決。
環境は、WindowsXP Professional、Apache 1.3.28
一応、インストールの手順を書いておきます。
php.netから、windows binaryをダウンロード。
phpは、C:\Program Filesの直下に置くことにする。
install.txtに従って、
Apacheのhttpd.confに、
LoadModule php4_module "C:\Program Files\php\sapi\php4apache.dll"
を追加。(1年前に設定していたみたいだ)
AddType application/x-httpd-php .php
も設定されている。
phpディレクトリ直下のphp.ini-recommendedを、C:\Windows直下にコピーして、php.iniにリネーム。
細かい設定は、後日することにしてとりあえずは、デフォルトのまま。
WindowsのPATHを設定。
「マイコンピータ」の「プロパティ」-「詳細設定」タブ−「環境変数」の「システム環境変数」のPathに追記するか、あるいは、コマンドプロンプトで、
ここで、Apacheをstartしてみる。
怒られてしまう。なぜだ。
Pathをよく確認すると、なぜか、C:\Windows\Program Files\php になっている。
Program Filesは、Cドライブの直下のはず。再度設定を確認すると、環境変数の設定で、
%SystemRoot%\Program Files\php
としてしまっていた。
な〜んだ。
設定を正しくして、再度Apacheを起動。
今度は、
だめらしい。
しょうがないので、C:\Windows\System32 に、php直下のphp4ts.dllをコピーしてみる。
再度、Apache起動。
やっと、起動しました。
Pathの設定をすれば、php4ts.dllをコピーしなくてもいいって、install.txtに書いてあるような気がするんだけど。
よくわからんです。
今日、やりたかったことは、pearのPHPUnitをインストールすることだったので、コマンドプロンプトから、。
いろいろでてくる質問に適当に答えるだけで、pearコマンドのインストール完了。