45
48

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

QUnitとは

JavaScript用のTestingFrameworkです。

由来

jQueryのテスト用に作られ、今もjQuery、jQuery-UIのテストに使われています。
それ自体はjQueryに依存していませんが、テスト内でDOMを操作したりイベントを生成したりするのにjQueryを使うと便利です。

JavaScript的な側面

実行環境

QUnitとテスト用のスクリプトをブラウザに読み込んで実行します。
テスト結果はそのままブラウザに表示します。

他のツールと連携すると

  • PhantomJSを使えばCLIで実行可能
  • Testemを使うとテスト修正時の自動リロード(再実行)が可能
  • Gruntからもgrunt-contrib-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.js
test("hello test", function() {
  ok(1 == "1", "passed!");
});

TestingFramewokとしての側面

xUnitの一種である。テストケースとアサートでテストを記述する。
ちなみに、JasmineというTestingFrameworkはBDD形式で記述します。

テストケース

テストケースはtestという関数で記述します。

test("hello test", function() {
	ok(1 == "1", "passed!");
});

第一引数がテストケース名で第二引数に内容を書きます。

アサート

アサート用の関数は3種類あります。

  1. ok
  2. equal
  3. 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」にチェックを入れても一緒です。

参考

45
48
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45
48

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?