PHPマニュアル/PEARマニュアル | ユーザフォーラムで議論/質問 | マニュアル検索 | ハイライト | ハイライトオフ | ポータル | php spot

チュートリアル | JavaScript入門&応用&リファレンスなら「JavaScriptist」

  

チュートリアル

チュートリアル – PHPUnit 簡易チュートリアル

テストフレームワークの紹介

PHPUnit は、関数やクラスを自動的にテストする "テストスイート" を作成するためのシンプルなフレームワークを提供します。 PHPUnit は、JUnit からヒントを得ています。 JUnit は、Kent Beck と Erich Gamma が、 eXtreme Programming (XP) 用のツールとして作成したソフトウエアです。XP においては、 小さなソフトウエアコンポーネントを可能な限り早期に頻繁に試験すること、 というルールが定められています。こうすることで、 アプリケーション全体を設定し試験する際になってまで、コンポーネント内部のバグやエラーを 修正する破目にならなくてすみます。ユニットテストと呼ばれるこういったコンポーネント毎の テストは XP の基本原則のひとつですが、だからといって PHPUnit を利用するために XP を実行しないといけない訳ではありません。 PHPUnitは、単体として、クラスや関数をテストする有効なツールであり、 際限のないデバッグ作業を避けるのに有用です。

実行手順

これまでに行われている良くあるテスト手順は、何らかのクラスを作成した後、 echo()var_dump() を用いて非体系的にテストを行い、不具合が発生しないことを願う、という流れでしょう。 PHPUnit を使って利益を得るためには、この流れを再考する必要があります。 最善の手順は、以下の通り行うことです。

  • 1. クラス/ API を設計

  • 2. テスト用ツールを作成

  • 3. クラス/ API を実装

  • 4. テスト用ツールを実行

  • 5. 失敗またはエラーを修正し、再度 #4 へ進む

この手順を踏むと時間が多く必要となるように見えますが、その印象は誤りです。 PHPUnit を使ってテストスイートを作成するには数分しかかからず、 テストスイートの実行にも、数秒しかかかりません。

クラスの設計

簡単な例として、文字列を処理するクラスを取り上げます。 まず、文字列処理を行う一連の関数の宣言を以下のように作成します。

<?php
//---- string.php ----

class String
{
    
// 内部データを保持
    
var $data;

    
// コンストラクタ
    
function String($data) {
        
$this->data $data;
    }

    
// 文字列オブジェクトのコピーを生成
    
function copy() {
    }

    
// 文字列をこのオブジェクトに付加
    
function add($string) {
    }

    
// フォーマット済み文字列を返す
    
function toString($format) {
    }
}
?>

テストスイートの作成

次に、この文字列処理クラスの各関数をテストするテストスイートを作成します。 テストスイートは、 PHPUnit_TestCase を継承した通常の PHP クラスで、このクラス中に 名称が 'test' で始まる "テスト関数" を定義していきます。 テスト関数においては、テスト対象の関数の帰り値と ありうべき正しい値との比較を行います。 この比較は、assert*() 系の関数を使って行い、 テストに合格したかどうかの判断が行われます。

<?php
//---- testcase.php ----

require_once 'string.php';
require_once 
'PHPUnit.php';

class 
StringTest extends PHPUnit_TestCase
{
    
// 文字列処理クラスのオブジェクト
    
var $abc;

    
// このテストスイートのコンストラクタ
    
function StringTest($name) {
       
$this->PHPUnit_TestCase($name);
    }

    
// テスト関数が実行される前にコールされる
    // この関数は PHPUnit_TestCase にて定義されており、
    // ここでオーバーライドしている
    
function setUp() {
        
// 新しいインスタンスを文字列'abc'を設定して作成
        
$this->abc = new String("abc");
    }

    
// テスト関数が実行された後にコールされる
    // この関数は PHPUnit_TestCase にて定義されており、
    // ここでオーバーライドしている
    
function tearDown() {
        
// インスタンスの削除
        
unset($this->abc);
    }

    
// toString 関数のテスト
    
function testToString() {
        
$result $this->abc->toString('contains %s');
        
$expected 'contains abc';
        
$this->assertTrue($result == $expected);
    }

    
// copy 関数のテスト
    
function testCopy() {
      
$abc2 $this->abc->copy();
      
$this->assertEquals($abc2$this->abc);
    }

    
// add 関数のテスト
    
function testAdd() {
        
$abc2 = new String('123');
        
$this->abc->add($abc2);
        
$result $this->abc->toString("%s");
        
$expected "abc123";
        
$this->assertTrue($result == $expected);
    }
  }
?>

テストの実行

それでは、テストを実行してみましょう。 パスが正しいか確認し、この PHP プログラムを実行してください。

<?php
//---- stringtest.php ----

require_once 'testcase.php';
require_once 
'PHPUnit.php';

$suite  = new PHPUnit_TestSuite("StringTest");
$result PHPUnit::run($suite);

echo 
$result -> toString();
?>

コマンドラインで実行すると、以下の出力が得られます。


TestCase stringtest->testtostring() failed: expected true, actual false
TestCase stringtest->testcopy() failed: expected , actual Object
TestCase stringtest->testadd() failed: expected true, actual false

まだ実装が行われておらず、各文字列処理関数は正しい値を返しませんので、 すべての関数がテストに不合格となります。

ブラウザから実行したい場合は、 $result->toString()$result->toHTML () へ変更してください。HTML ページが出力されます。

実装

文字列処理クラスの実装を行いましょう。

<?php
//---- string.php ----

class String
{
    
// 内部データを保持
    
var $data;

    
// コンストラクタ
    
function String($data) {
        
$this->data $data;
    }

    
// 文字列オブジェクトのコピーを生成
    
function copy() {
        
$ret = new String($this->data);
        return 
$ret;
    }

    
// 文字列をこのオブジェクトに付加
    
function add($string) {
        
$this->data $this->data.$string->toString("%ss");
    }

    
// フォーマット済み文字列を返す
    
function toString($format) {
        
$ret sprintf($format$this->data);
        return 
$ret;
    }
}
?>

実装が終了したら、テストを実行します。

~>
php -f stringtest.php
TestCase stringtest->testtostring() passed
TestCase stringtest->testcopy() passed
TestCase stringtest->testadd() failed: expected true, actual false

あれ、最後のテストが不合格です。タイプミスをしたようです。 string.php の 16 行目を以下の様に修正します。

<?php
$this
->data $this->data.$string->toString("%s");
?>

そして、テストを再実行します。

~>
php -f stringtest.php
TestCase stringtest->testtostring() passed
TestCase stringtest->testcopy() passed
TestCase stringtest->testadd() passed

すべて合格しました。

まとめ

たった3つの単純な関数しかないクラスに対しては、大袈裟な手順かも知れません。 しかし、上記は短い例に過ぎないのであって、オンラインショップの ショッピングカートやデータベース抽象化クラスなどの、 大きくて複雑な API を持つクラスを考えて見てください。 PHPUnit は、実装中に潜むバグを見つけるのに非常に有用なツールなのです。

また、以前に使ったクラスの再実装をするような場合を考えると、 テストスイート無しでは、そのクラスに依存するアプリケーションに 不具合を発生させる可能性が高くなります。 まずテストスイートを作成し、新しいクラスがテストにすべて合格するように保ったまま 再実装を行っていけば、アプリケーションに不具合が起きる事はないでしょう。

忘却曲線を使ってこの知識を確実に記憶に残す

フォーラムで「チュートリアル」について話す
各種マニュアル: PHPマニュアル | PEARマニュアル | Smarty(英語)マニュアル | PHP-GTKマニュアル | チュートリアル」をGoogle検索
copyright © 1997-2024 PHP ドキュメント作成グループ(ライセンス). provided by php spot. マニュアル: