2010年5月18日火曜日

遅まきながらの・・・PHPUnit

前からやろうと思いつつ、後回しにしていたユニットテスト。
遅まきながら手を動かすことにしました。

PHPUnit


これからはアジャイルですよ、テスト駆動型ですよ、と思いつつも後回しにしていたユニットテスト。今後、長く使っていたライブラリのリファクタリングが出てきそうなので、PHPUnitを導入。

似たようなのにSimpleTestというのも見つけた。
どうも機能としては、こちらのほうがいいらしい。

が、ウェブサイトをちょっと見て、最新版が2年前リリースされたまま。微妙にサポートを心配したり、やはり有名どころを使うのがよいだろう、と判断して無難にPHPUnitを使うことにした。

インストール

Pear経由でインストールするとのこと。
そういえば開発環境のPearは何年もアップデートしていない。
しかもVista上にXamppを使って環境作ったためか、いきなりCLI版が動かない。
対応方法はphp.iniのphp_mysqli.dllをコメントアウト

ついでにVistaのコンピュータ→プロパティ(あるいはコントロールパネルのシステム)→システムの詳細設定→環境設定→システム環境変数の「Path」にPHP.exeのあるフォルダーを追加。

いよいよPearのフォルダ (\xampp\PHP)で作業。
確か、以下のコマンドを打ち込んだら動いた。

pear channel-discover pear.phpunit.de
pear channel-discover pear.symfony-project.com
pear upgrade --force PEAR
pear install phpunit/PHPUnit

ここまでで半日以上使ってる。

ユニットテスト

早速コードを書いてみた。カートクラスをテストしてみよう。

require_once( "PHPUnit/Framework.php" );
class CartTest extends PHPUnit_Framework_TestCase
{
    private $cart;
    public function setUp()
    {
        $this->cart = new svCart();
    }
    function testAdd() {
        $this->cart->add( '100', 1 );
        $cart = $this->cart->get_list();
        $this->assertEquals( $cart[0]['pid'], '100' );
        $this->assertEquals( $cart[0]['num'], 1 );
    }
}

「testCart.php」とかいう名前で保存して動かしたら・・・動いた。
そりゃそうだ。

が、いちいちコマンドを叩くなんて、非常に原始的だ。
もうシェルなんか、ましてはcmdなんて、コピペすら出来ない。
ので、簡単にウェブから走るようにした。

if( preg_match( '/[-_a-zA-Z0-9]+/', $_REQUEST[ 'test' ] ) ) {
    $test = $_REQUEST[ 'test' ];
    $msg  = do_unittest( $test, $result );
}

function do_unittest( $test, &$result )
{
    $cwd     = dirname( __FILE__ );
    $command = "PHPUnit {$cwd}/{$test}.php";
    $results = my_exec( $command );
    
    $result = $results[ 'stderr' ];
    return $results[ 'stdout' ];
}

function my_exec( $cmd, $input='' )
{
    $proc = proc_open( 
        $cmd, 
        array( 
            0 => array('pipe', 'r'), 
            1 => array('pipe', 'w'), 
            2 => array('pipe', 'w')
        ), 
        $pipes
    );
    fwrite( $pipes[0], $input );                fclose( $pipes[0] );
    $stdout = stream_get_contents( $pipes[1] ); fclose( $pipes[1] );
    $stderr = stream_get_contents( $pipes[2] ); fclose( $pipes[2] );
    $rtn    = proc_close( $proc );
    return array(
        'stdout' => $stdout,
        'stderr' => $stderr,
        'return' => $rtn
    );
} 

この「my_exec」というのはPHP.netのsystemに書いてあるコード。
PHPUnitはメッセージをstdoutとstderrの両方に書き込むので、必要になった。後は「test.php?test=testCart」とか叩くようにするとテスト結果が出る。

【追記:あ~セキュリティホール見つけた!】

0 件のコメント: