mofmof.js のUnit Test機能
mofmof.js にはユニットテスト機能があり、同期/非同期テストの混在や遅延評価もシンプルに記述できます。
以下のコードは、http://mofmof-js.googlecode.com/svn/trunk/test/base.js.htm でテストできます。
同期/非同期の混在
String#test は String#stream の機能を流用して実装されており、
同期/非同期のテストを混在する事ができます。
String#stream と異なり、項目が false を返しても最後まで実行します。
テストしたいを目的に応じて、 関数, 配列, 真偽値 の何れかで定義します。
"関数で評価 > 配列の要素2つを比較 > 真偽値評価".test({ args: { msg: "hello" }, "関数で評価": function() { return this.args.msg === "hello"; // -> true }, "配列の要素2つを比較": ["aaa", "aaa"], // -> true "真偽値評価": 123 === 123 // -> true });
実行結果です。
[ 02-14T09:45:25.484Z ]:┌ 関数で評...() [ 02-14T09:45:25.485Z ]:│ 関数で評...[ 関数で評価, true ] [ 02-14T09:45:25.485Z ]:│ 関数で評...[ 配列の要素2つを比較, true ] [ 02-14T09:45:25.486Z ]:│ 関数で評...[ 真偽値評価, true ] [ 02-14T09:45:25.487Z ]:└ 関数で評...(span:00.003)
関数で定義
関数は同期/非同期テスト用です。 this を使って hash に定義されている変数を参照可能です。また非同期に結果を返す事ができます。
"関数で遅延評価".test({ args: { msg: "hello" }, "関数で遅延評価": function(callback) { 3..lazy(this, function() { // 3秒後に関数を遅延実行, 関数内部の this を指定 callback(this.args.msg === "hello"); // callback(true) }); } });
実行結果です。
[ 2012-02-14T09:46:08.208Z ]: ┌ 関数で遅延評価() [ 2012-02-14T09:46:11.208Z ]: │ 関数で遅延評価[ 関数で遅延評価, true ] [ 2012-02-14T09:46:11.226Z ]: └ 関数で遅延評価(span:03.018)
配列で定義
2つの要素をもつ配列を指定すると Type.isLike(配列の先頭要素, 配列の2番目の要素) で比較を行い、結果を true / false として評価します。
"配列の要素2つを比較".test({ "配列の要素2つを比較": ["aaa", "aaa"] // -> true });
実行結果です。
[ 2012-02-14T09:47:01.915Z ]: ┌ 配列の要素2つを比較() [ 2012-02-14T09:47:01.916Z ]: │ 配列の要素2つを比較[ 配列の要素2つを比較, true ] [ 2012-02-14T09:47:01.916Z ]: └ 配列の要素2つを比較(span:00.001)
真偽値で定義
真偽値も使えます。
Type.isLike 以外の関数で評価する場合などに使用できます。
"anagram".test({ "anagram": "JavaScript".anagram("JScript") // -> true });
実行結果です。
[ 02-14T10:15:47.555Z ]:┌ anagram() [ 02-14T10:15:47.557Z ]:│ anagram[ anagram, true ] [ 02-14T10:15:47.559Z ]:└ anagram(span:00.004)
this.log でログを出力できます
String#test は、this.log(...) とすることでログを出力できます。
"a > async1 > async2 > b > c".test({ args: { msg: "hige" }, a: function() { return this.args.msg === "piyo"; // -> false }, b: ["aba", "aaa"], // -> false c: 123 === 456, // -> false async1: function(callback) { 2..lazy(null, callback); }, async2: function(callback) { 2..lazy(this, function() { this.log("LOG OK!"); callback(true); // -> true }); } });
実行結果です。
[ 14T09:52:19.082Z ]:┌ a > async1 > async2 > b > c() [ 14T09:52:19.105Z ]:│ a > async1 > async2 > b > c[ a, false ] [ 14T09:52:21.106Z ]:│ a > async1 > async2 > b > c[ async1, ] [ 14T09:52:23.106Z ]:│ a > async1 > async2 > b > c[ LOG OK! ] [ 14T09:52:23.107Z ]:│ a > async1 > async2 > b > c[ async2, true ] [ 14T09:52:23.108Z ]:│ a > async1 > async2 > b > c[ b, false ] [ 14T09:52:23.109Z ]:│ a > async1 > async2 > b > c[ c, false ] [ 14T09:52:23.110Z ]:└ a > async1 > async2 > b > c(span:04.028)
存在しない関数や項目を指定するとエラーで中断します
存在しない項目があればテストを中断します。
"a > b> c".test({ a: true, b: true, // c: true });
実行結果です。
[ 2012-02-14T09:53:31.110Z ]: ┌ a > b> c() [ 2012-02-14T09:53:31.110Z ]: │ a > b> c[ a, true ] [ 2012-02-14T09:53:31.111Z ]: │ a > b> c[ b, true ] [ 2012-02-14T09:53:31.112Z ]: │ a > b> c[ c, ERROR ]
Array#test でもっとシンプルに
String#test の簡易版、Array#test もあります。
以下のように関数名を並べるだけでテストできます。
function async1(callback) { 2..lazy(null, callback); } function async2(callback) { 2..lazy(this, function() { this.log("OK!"); callback(true); }); } [async1, async2].test(); // テスト実行
実行結果です。
[ 14T09:57:19.675Z ]:┌ async1 > async2() [ 14T09:57:21.676Z ]:│ async1 > async2[ async1, ] [ 14T09:57:23.676Z ]:│ async1 > async2[ OK! ] [ 14T09:57:23.677Z ]:│ async1 > async2[ async2, true ] [ 14T09:57:23.678Z ]:└ async1 > async2(span:04.003)
例外発生をテストする
例外が発生することをテストしたいケースがあります。そのような場合は try ~ catch で囲ってください。
function catchError() { try { throw new Error("ERROR"); } catch (err) { return true; } return false; } [catchError].test();
実行結果です。
[ 02-14T10:00:33.294Z ]:┌ catchError() [ 02-14T10:00:33.295Z ]:│ catchError[ catchError, true ] [ 02-14T10:00:33.296Z ]:└ catchError(span:00.002)
まとめ
いかがだったでしょうか。
従来の Unit Test に比べ、コード量も少なく環境も汚染しません。
(ε・◇・)з テストめんどくさー
と言わずにどんどんテストしましょう → (ε・◇・)з