はじめに
プログラミングの勉強のため、鍋谷さん主催の オフラインリアルタイムどう書く の問題を解いている (あまり参加はできていませんが)。問題を解く際はテストも書くのだが、私のテストの書き方がイマイチなため、テストコードの書き方を勉強しようと思い、学習内容をまとめることにした。
今回は未回答だった Tick-Tack-Toe 〜 横へな 2012.7.6 を題材にテストの書き方について勉強した。私の書いたコードは ここ から閲覧可。
従来のテストコード
従来は下記の様なコードを書いていたが、失敗するテストケースがあった場合、どのテストで失敗したのかがわかりにくいという問題点がある。
var tick_tack_toe = require('./tick_tack_toe');
describe("tick_tack_toe.solve", function() {
var inputs = [
['79538246', 'x won.'],
// 以下略
];
it("should return expected msg.", function() {
for(var i = 0; i < inputs.length; ++i) {
expect( tick_tack_toe.solve(inputs[i][0]) ).toBe(inputs[i][1]);
}
});
});
以下の様に書くと、どのテストで失敗したかがわかるが、無様すぎる。
var tick_tack_toe = require('./tick_tack_toe');
describe("tick_tack_toe.solve", function() {
it("should return 'x won.' (1).", function() {
expect( tick_tack_toe.solve('79538246') ).toBe('x won.');
});
it("should return 'x won.' (2).", function() {
expect( tick_tack_toe.solve('35497162193') ).toBe('x won.');
});
// 以下略
});
もうちょっと良い書き方はないかと調べていたところ、 Parameterized Test という手法を知ったので、 Parameterized Test についてまとめることにした。
Parameterized Test とは
似たようなテストメソッドをテストデータだけ変えて複数件実行するための手段。今回やりたいことは「solve 関数のテストを、 solve に渡す引数だけを変えて複数件実行すること」なので、本手法により目的を達成することができる。
上記テストコードに Parameterized Test を適用する
テストフレームワークの機能として提供されているのかと思ったが、今回使用した Jasmine-node には無さそう。仕方ないので、下記の様なコードで対応することにした。
var tick_tack_toe = require('./tick_tack_toe');
describe("tick_tack_toe.solve", function() {
var inputs = [
['79538246', 'x won.'],
// 以下略
];
for(var i = 0; i < inputs.length; ++i) {
(function(src, expected) {
it("should return " + expected + " (" + i + ").", function() {
var actual = tick_tack_toe.solve(src);
expect(actual).toBe(expected);
});
})(inputs[i][0], inputs[i][1]);
}
});
どのテストデータで失敗したかがわかる分、一番初めに載せたテストコードよりはマシと思うことにする。
補足
Jasmine / QUnit では、 Parameterized Test を行うためのプラグインが提供されている。