マイナー・マイナー

隠れた名作の発掘が生きがい。

QUnitを用いた単体テストの実装例


スポンサードリンク

QUnitとは、JavaScriptのテストフレームワークのひとつです。触ってみた感じ、テストコードへの依存性が少なく、導入も簡単にできました。このQUnitを使って、下記のような関数をテストするサンプルコードを作りました。

(1) 戻り値ありの関数
(2) 引数がコールバックの関数
(3) 別の関数が応答となる関数

導入

下記のQUnit公式ページより、「qunit-1.14.0.css」と「qunit-1.14.0.js」をダウロードします。

https://qunitjs.com/


ダウンロードしたファイルを適当なフォルダに配置します。ここではフォルダ構成を下記のようにしました。「hoge.js」はテスト対象の関数を記述し、「unit-test.js」にテストコードのサンプルを記述します。「unit-test.html」はテストの実行結果を表示するファイルです。


フォルダ構成

/
∟qunit
 ∟qunit-1.14.0.css
 ∟qunit-1.14.0.js
∟test
 ∟hoge.js
 ∟unit-test.html
 ∟unit-test.js


unit-test.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Unit Test</title>
  <!-- QUnitレポート用CSSをインポート -->
  <link rel="stylesheet" href="../qunit/qunit-1.14.0.css">
  <!-- QUnitをインポート -->
  <script type="text/javascript" src="../qunit/qunit-1.14.0.js"></script>
  <!-- テスト対象コードをインポート -->
  <script type="text/javascript" src="./hoge.js"></script>
  <!-- テストコードをインポート -->
  <script type="text/javascript" src="./unit-test.js"></script>
</head>
<body>
  <!-- テスト結果表示 -->
  <div id="qunit"></div>
</body>
</html>

(1) 戻り値ありの関数

下記2つの関数のテストコードを考えます。

・引数なし関数(hoge1)
・引数あり関数(hoge2)


テストのグループ化はmoduleメソッドで実装します。第一引数はグループ化した名前、第二引数はテスト前処理関数(setup)、テスト後処理関数(teardown)等を指定します。


テストはtestメソッドで実装できます。第一引数にはテストの名前、第二引数にはテストコードを記述します。テストの検証はokメソッド等を使います。ok(検証式、検証メッセージ)の形式で記載します。検証メソッドは他にequal、strictEqualや、例外検証のthrowなどがあります。


hoge.js

// ----- テスト関数定義 -----
var Hoge = function() {};

// 引数なし関数
Hoge.prototype.hoge1 = function() {
  return 0;
};

// 引数あり関数
Hoge.prototype.hoge2 = function(value) {
  if (value == 1) {
    return 10;
  }
  return 0;
};


unit-test.js

var hoge;

module("Hogeテスト", {
  // 単体テスト準備
  setup: function () {
    hoge = new Hoge();
  }
});

// 単体テスト開始
test("引数なし関数", function () {
  // 検証
  ok(hoge.hoge1() == 0, "OK"); // OK
});

test("引数あり関数", function () {
  // 検証
  ok(hoge.hoge2(0) == 0, "OK"); // OK
  ok(hoge.hoge2(1) == 10, "OK"); // OK
});


テスト結果は下記画像のような感じとなりました。エラーがあれば赤くなります。

f:id:yosinoo:20140324220828p:plain

(2) 引数がコールバックの関数

次のコールバック関数を引数とする関数のテストを考えます。

・引数なしのコールバック関数(hoge3)
・引数ありのコールバック関数(hoge4)


これらの関数は、検証用のコールバック関数を準備し、そのコールバック関数の中で実行結果を取得して検証すれば良さそうです。


hoge.js

// ----- テスト関数定義 -----
var Hoge = function() {};

// 引数なしのコールバック関数
Hoge.prototype.hoge3 = function(callbackFunc) {
  callbackFunc();
};

// 引数ありのコールバック関数
Hoge.prototype.hoge4 = function(callbackFunc) {
  callbackFunc(10);
};


unit-test.js

var hoge;

module("Hogeテスト", {
  // 単体テスト準備
  setup: function () {
    hoge = new Hoge();
  }
});

test("引数なしのコールバック関数", function () {
  // 検証用コールバック関数の準備
  var result = 0;
  var callbackResult = function () {
    result = 1;
  };

  // 検証
  hoge.hoge3(callbackResult);
  ok(result == 1, "OK"); // OK
});

test("引数ありのコールバック関数", function () {
  // 検証用コールバック関数の準備
  var result = 0;
  var callbackResult = function (value) {
    result = value;
  };

  // 検証
  hoge.hoge4(callbackResult);
  ok(result == 10, "OK"); // OK
});

(3) 別の関数が応答となる関数

ある関数を呼び出すと、応答結果として別の関数が呼ばれるケースを考えます(通信のリクエスト・レスポンス等のケースです)。


応答関数が何かの応答結果を保存している場合、テスト関数を呼び出した後にその応答結果を検証すれば良さそうです。応答が非同期で時間がかかる場合、その時間を見越してsetTimeoutで応答結果を待つようにします。


testメソッドは非同期で実行されているようなので、非同期な関数のテストにはasyncTestメソッドを用いるのが良さそうです。asyncTestメソッドはstart()が呼ばれるまで他のテスト実行を止めます。


hoge.js

// ----- テスト関数定義 -----
var Hoge = function() {
  var _result_hoge5 = 0;
};

// 要求関数(応答はhoge5_2)
Hoge.prototype.hoge5_1 = function() {
  Hoge.prototype.hoge5_2(10);
};

// 応答関数(要求はhoge5_1)
Hoge.prototype.hoge5_2 = function(result) {
   setTimeout(function(){
      _result_hoge5 = result;
   }, 500); // 0.5秒後に応答結果をセット
};

// 結果取得関数
Hoge.prototype.getResultHoge5 = function() {
  return _result_hoge5;
};


unit-test.js

var hoge;

module("Hogeテスト", {
  // 単体テスト準備
  setup: function () {
    hoge = new Hoge();
  }
});

asyncTest("別の関数が応答となる関数", function () {
  // 検証
  hoge.hoge5_1();
  setTimeout(function(){
      ok(hoge.getResultHoge5() == 10, "OK"); // OK
      start();
    }, 1000); // 1秒後に応答結果検証
});


応答関数が応答結果を保存しない場合の検証は、応答関数をオーバライドするなどが必要だと思います。