QUnitとは
JavaScript用のTestingFrameworkです。
由来
jQueryのテスト用に作られ、今もjQuery、jQuery-UIのテストに使われています。 それ自体はjQueryに依存していませんが、テスト内でDOMを操作したりイベントを生成したりするのにjQueryを使うと便利です。
JavaScript的な側面
実行環境
QUnitとテスト用のスクリプトをブラウザに読み込んで実行します。 テスト結果はそのままブラウザに表示します。
他のツールと連携すると
ちなみに、mochaというTestingFrameworkはnode.jsで実行します。
インストール
npmで入れることもできますが、scriptタグでブラウザに読み込むのでソースをローカルに置くか、CDNから取得するのが一般的です。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>QUnit Example</title> <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.12.0.css"> </head> <body> <div id="qunit"></div> <div id="qunit-fixture"></div> <script src="http://code.jquery.com/qunit/qunit-1.12.0.js"></script> <script src="tests.js"></script> </body> </html>
test.jsはこのような内容です。
test("hello test", function() { ok(1 == "1", "passed!"); });
TestingFramewokとしての側面
xUnitの一種である。テストケースとアサートでテストを記述する。 ちなみに、JasmineというTestingFrameworkはBDD形式で記述します。
テストケース
テストケースはtestという関数で記述します。
test("hello test", function() { ok(1 == "1", "passed!"); });
第一引数がテストケース名で第二引数に内容を書きます。
アサート
アサート用の関数は3種類あります。
- ok
- equal
- throws
OK
真であるか判定します。
test("ok test", function() { ok(true, "true succeeds"); ok("non-empty", "non-empty string succeeds"); ok(false, "false fails"); ok(0, "0 fails"); ok(NaN, "NaN fails"); ok("", "empty string fails"); ok(null, "null fails"); ok(undefined, "undefined fails"); });
equal
二つの値が同じであるか判定します。
test("equal test", function() { equal(0, 0, "Zero, Zero; equal succeeds"); equal("", 0, "Empty, Zero; equal succeeds"); equal("", "", "Empty, Empty; equal succeeds"); equal("three", 3, "Three, 3; equal fails"); equal(null, false, "null, false; equal fails"); });
equalは==で比較するため型変換されます。===で比較するstrictEqual関数もあります。
test("strict equal test", function() { strictEqual(0, 0, "Zero, Zero; strict equal succeeds"); strictEqual("", 0, "Empty, Zero; strict equal failss"); strictEqual("0", 0, "String Zero, Number Zero; strict equal failss"); });
オブジェクトや配列の中身を比較するdeepEqualもあります。
test("deepEqual test", function() { var obj = { foo: "bar" }; deepEqual(obj, { foo: "bar" }, "Two objects can be the same in value"); });
それぞれ異なることを判定するための関数があります。
- notEqual
- notStrictEqual
- notDeepEqual
throws
例外が出ることを確認します。
test("throws", function() { throws( function() { throw "error" }, "throws with just a message, no expected" ); });
Callbackのテスト
Callback関数が呼ばれるかどうかをテストする方法があります。
同期コールバック
イベントハンドラーなどの即座に呼び出されるコールバックの確認にはexpect関数を使います。
test("a test", function() { expect(1); var $body = $("body"); $body.on("click", function() { ok(true, "body was clicked!"); }); $body.trigger("click"); });
expectの引数は想定する、okなどアサート関数の呼び出し回数です。 test関数の第二引数に指定することもできます。
test("a test", 1, function() { var $body = $("body"); $body.on("click", function() { ok(true, "body was clicked!"); }); $body.trigger("click"); });
非同期コールバック
Ajaxなどの即座に帰ってこないコールバックはコールバックの呼び出しを待つことができます。 このときはtest関数の代わりにasyncTest関数を使います。
asyncTest("asynchronous test: video ready to play", 1, function() { var $video = $("video"); $video.on("canplaythrough", function() { ok(true, "video has loaded and is ready to play"); start(); }); });
テストの実行を止め、start関数が呼ばれるまで待ちます。
テストケースのグループ化
module関数を使うとテストケースをグループ化できます。
module("group a"); test("a basic test example", function() { ok(true, "this test is fine"); }); test("a basic test example 2", function() { ok(true, "this test is fine"); }); module("group b"); test("a basic test example 3", function() { ok(true, "this test is fine"); }); test("a basic test example 4", function() { ok(true, "this test is fine"); });
モジュールにはsetup/teadown関数を指定してできます。これらの関数は各テストの実行前後に呼び出されます。
module("module", { setup: function() { ok(true, "one extra assert per test"); }, teardown: function() { ok(true, "and one extra assert after each test"); } }); test("test with setup and teardown", function() { expect(2); });
その他
テスト対象のDOM
テスト対象のDOMはqunit-fixture要素に追加します。 qunit-fixture要素はテスト終了毎にクリアされます。 テスト同士が影響を及ぼしあうのを防ぎます。
test("Appends a div", function() { var $fixture = $("#qunit-fixture"); $fixture.append("<div>hello!</div>"); equal($("div", $fixture).length, 1, "div added successfully!"); }); test("Appends a span", function() { var $fixture = $("#qunit-fixture"); $fixture.append("<span>hello!</span>"); equal($("span", $fixture).length, 1, "span added successfully!"); });
ユーザ操作のエミュレーション
jQueryのtrigger関数を使ってください。
グローバル汚染チェック
テスト実行時のURLのクエリパラメータに noglobals=true を指定するとテスト内でグローバル変数が追加・削除されていない確認することができます。 結果画面のチェックボックス「Check for Globals」にチェックを入れても一緒です。