PHPでTAP(Test Anything Protocol)を使う

TAP(Test Anything Protocol)とは、テストを簡潔に記述するための書き方(プロトコル)のことです。

プロトコルというと難しそうですが、実際はとても簡単。標準出力に、以下のような出力を行うプログラムを作成すればよいのです。

    1..4
ok 1 - Input file opened
not ok 2 - First line of the input valid
ok 3 - Read the rest of the file
not ok 4 - Summarized correctly # TODO Not written yet 

要点は
(1) 最初の行に、テストの件数を表示する
(2) 2行目以降に、テスト結果(ok/not ok)・テスト番号・説明を表示する
以上。

なお、2行目以降の必須項目はテスト結果(ok/not ok)だけです。
テスト番号は無くてもエラーにはならないものの、あったほうがよい(実行予定テストの総数と、実際に走ったテストの総数が異なっている時に警告が出る)。
説明は、後で読む人のためにも書いておいたほうがよいです。

それでは実際に書いてみます。

tap.php

<?php
/**
* @param int $number_of_tests
*/
function test($number_of_tests = 0)
{
if ($number_of_tests > 0) {
echo '1..', $number_of_tests, PHP_EOL;
}
}
/**
* @param        $got
* @param        $expected
* @param int    $test_number
* @param string $description テストの説明
* @param string $directive   「TODO」又は「SKIP」+ TODO/SKIPである理由
*/
function is($got, $expected, $test_number, $description = '', $directive = '')
{
if ($expected === $got) {
echo 'ok ', $test_number;
} else {
echo 'not ok ', $test_number;
}
if ($description !== '') {
echo ' - ', $description;
}
if ($directive !== '') {
echo ' # ' . $directive;
}
echo PHP_EOL;
if ($expected !== $got) {
echo '# got:      ', $got, PHP_EOL;
echo '# expected: ', $expected, PHP_EOL;
}
}

fizzbuzz.php

<?php
function fizzbuzz($n) {
return $n;
}

fizzbuzz.t

#!/usr/bin/env php
<?php
error_reporting(E_ALL);
require_once 'tap.php';
require_once 'fizzbuzz.php';
test(15);
is(fizzbuzz(1), 1, 1);
is(fizzbuzz(2), 2, 2);
is(fizzbuzz(3), 'fizz', 3, '三の倍数');
is(fizzbuzz(4), 4, 4);
is(fizzbuzz(5), 'buzz', 5, '五の倍数');
is(fizzbuzz(6), 'fizz', 6, '三の倍数');
is(fizzbuzz(7), 7, 7);
is(fizzbuzz(8), 8, 8);
is(fizzbuzz(9), 'fizz', 9, '三の倍数');
is(fizzbuzz(10), 'buzz', 10, '五の倍数');
is(fizzbuzz(11), 11, 11);
is(fizzbuzz(12), 'fizz', 12, '三の倍数');
is(fizzbuzz(13), 13, 13);
is(fizzbuzz(14), 14, 14);
is(fizzbuzz(15), 'fizzbuzz', 15, '三の倍数 かつ 五の倍数');

TAPに従って書かれたテストを実行するには、proveというコマンドを使います。Perlの実行環境があるなら、インストールされているはず(Mac OS Xには標準で入っていますし、大抵のLinix/Unixには入っているでしょう)。

「prove fizzbuzz.t」を実行すると、「fizzbuzz.t .. Failed 7/15 subtests」と表示されます。15回のテストのうち、7回失敗したということです。「php fizzbuzz.t」を実行してみると、以下のような表示がされます。

not ok 3 – 三の倍数
# got:      3
# expected: fizz

最初のfizzbuzz.phpでは、fizzbuzzのロジックを組み込んでいなかったので、テストにこけるのは当たり前。fizzbuzz.phpの中身を差し替えましょう。

fizzbuzz.php

<?php
function fizzbuzz($n) {
if ($n % 15 === 0) {
return 'fizzbuzz';
}
if ($n % 5 === 0) {
return 'buzz';
}
if ($n % 3 === 0) {
return 'fizz';
}
return $n;
}

今度は、fizzbuzzのロジックをちゃんと組んであるので、テストに通るはずです。再度「prove fizzbuzz.t」を実行すると…「fizzbuzz.t .. ok」と表示されました!

このように、TAPを利用したテストは、*Unit等を使用したテストに比べ、(1) テストが簡単に書ける (2) 導入が非常に簡単である という特徴があります。

本格的なプロジェクトであれば、PHPUnit等のテスティングフレームワークを導入したほうがいいと思いますが、小規模なスクリプトのテストならTAPで十分でしょう。

<参考>

「同じコード」の同じって何さ – TAPのススメ
:tap.phpは、こちらのtap.rbのロジックをPHPで書き直し + 一部改変したものです。
TAP Specification:TAPの仕様

コメントを残す

コメントを残す