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の仕様