書籍転載:JavaScriptライブラリ実践活用[厳選111]

書籍転載:JavaScriptライブラリ実践活用[厳選111]

[QUnit]テストコードを実行し、ブラウザで結果を確認する

2013年5月30日

書籍転載の8本目(書籍内の番号は「111」)。JavaScript用テストランナーの定番ライブラリである「QUnit」の基礎と基本的な使い方を説明。

WINGSプロジェクト 高野 将
  • このエントリーをはてなブックマークに追加

書籍転載について

 本コーナーは、技術評論社発行の書籍『JavaScriptライブラリ実践活用[厳選111]』の中から、特にBuild Insiderの読者に有用だと考えられる項目を編集部が選び、同社の許可を得て転載したものです。

 『JavaScriptライブラリ実践活用[厳選111]』の詳細や購入は技術評論社のサイト目次ページをご覧ください。

ご注意

本記事は、書籍の内容を改変することなく、そのまま転載したものです。このため用字用語の統一ルールなどはBuild Insiderのそれとは一致しません。あらかじめご了承ください。

QUnitはjQueryのテストにも用いられている、JavaScript用テストランナーの定番ライブラリです。テスト実行結果用のWebページを用意してテストコードを書き、ブラウザで表示することで自動的にテストが実行され、結果が表示されます。

  • 名称: QUnit
  • 分類: フレームワーク
  • URL: http://qunitjs.com/
  • 関連ファイル: qunit-1.10.0.js、qunit-1.10.0.css
QUnitによるテスト実行結果
QUnitによるテスト実行結果

QUnitとは

 QUnitはJavaScript用のテストランナーです。もともとはjQueryのテスト用に作成されたライブラリで、jQueryのコードにはQUnitを用いたテストコードが含まれています。とはいえ、現在はjQueryへの依存はありませんので、独立して使用することができます。

 テストを実行するには、テストコードとテスト実行用のWebページを作成します。作成したWebページをWebブラウザで表示するだけで、テストの実行と結果表示が行われます。

 具体的にどのようにすればよいのか、説明していきましょう。

テスト対象コード

 今回はリスト111-01のような、作成中のFizzBuzzオブジェクトをテストします。テスト結果表示のため、あえて間違った実装にしています。

JavaScript
// 引数なし例外
var ArgumentNullException = function () { };

// FizzBuzz用クラス定義
var FizzBuzz = (function () {
  // FizzBuzzクラス作成
  var FizzBuzz = function () { };

  // 指定した値に対応するFizzBuzz結果を返すメソッド
  FizzBuzz.prototype.speak = function (n) {
    // 引数が設定されていなければエラー
    if (!n) throw new ArgumentNullException();
    // 3で割り切れるときはFizz
    if (n % 3 === 0) return "Fizz";
    // 5で割り切れるときはBuzz
    if (n === 5) return "Buzz";
    // 3でも5でも割り切れるときはFizzBuzz
    if (n % 3 === 0 && n % 5 === 0) return "FizzBuzz";
    // 上記いずれでもないときは引数のまま
    return n.toString();
  };

  // 定義したクラスを返す
  return FizzBuzz;
})();
リスト111-01 テスト対象コード(fizzbuzz-test.js)

テストコード

 QUnitのテストコードは、リスト111-02のように書きます。

JavaScript
var fizzBuzz;

// 1 テストのグルーピング
module("FizzBuzzの正常テスト", {
  // 2 セットアップ
  setup: function () {
    fizzBuzz = new FizzBuzz();
  }
});

// 3 テストケース定義
test("数字を返す", function () {
  // 4 検証
  ok(fizzBuzz.speak(1) === "1", "speak 1");
  ok(fizzBuzz.speak(2) === "2", "speak 2");
});

test("3の倍数でFizzを返す", function () {
  ok(fizzBuzz.speak(3) === "Fizz", "speak Fizz by 3");
  ok(fizzBuzz.speak(6) === "Fizz", "speak Fizz by 6");
});

test("5の倍数でBuzzを返す", function () {
  ok(fizzBuzz.speak(5) === "Buzz", "speak Buzz by 5");
  ok(fizzBuzz.speak(10) === "Buzz", "speak Buzz by 10");
});

test("3の倍数かつ5の倍数でFizzBuzzを返す", function () {
  ok(fizzBuzz.speak(15) === "FizzBuzz", "speak FizzBuzz by 15");
  ok(fizzBuzz.speak(30) === "FizzBuzz", "speak FizzBuzz by 30");
});

module("FizzBuzzの異常テスト", {
  setup: function () {
    fizzBuzz = new FizzBuzz();
  }
});

test("引数指定なしで例外発生", function () {
  // 5 例外検証
  throws(function () { fizzBuzz.speak(null); },
    ArgumentNullException, "argument required by null");
});
リスト111-02 テストコード(fizzbuzz-test.js)

1 テストのグルーピング

 moduleメソッドを使って、テストのグルーピングができます。グルーピングする範囲は次のmoduleメソッドが呼ばれるまでです。

 第1引数に指定した内容は、テスト結果を表示する際テストケースの先頭に付加されて表示されます(後述の「テスト実行結果」で掲載してる図111-01[5])。

2 セットアップ

 moduleメソッドの第2引数に渡すオブジェクトにsetupメソッドを定義すると、それぞれのテストケース前に実行されるセットアップ処理を行うことができます。サンプルではFizzBuzzオブジェクトの作成をsetupメソッドに定義します。

3 テストケース定義

 testメソッドを使うことで、1つのテストケースを定義します。第1引数にテストケースの内容を表す文言、第2引数に実際のテストを行う関数を指定します。

4 検証

 テストケース内の検証処理は、主にokメソッドを使って行います。第1引数に指定した式が偽と評価されると、テスト失敗とみなされます。第2引数に行う検証の説明を指定すると、テスト結果にテストケース毎に説明が表示されます(後述の「テスト実行結果」で掲載してる図111-01[5])。

5 例外検証

 「例外が発生すること」を検証するにはthrowsメソッドを使います。第1引数に検証対象の例外が発生する関数を指定し、第2引数に発生を検証したい例外の型を指定します。第3引数はokメソッドの第2引数と同じく、検証の説明を指定します。

 なお、アサーションに使用するメソッドを表111-01にまとめます。

メソッド説明
ok(検証式, メッセージ) 検証式が真と評価されるかどうか検証する
equal(検証値, 期待値, メッセージ) 検証値が期待値と同じ値とみなせるかどうか検証する(==による比較)
notEqual(検証値, 期待値, メッセージ) equalメソッドの逆で、同じ値と見なせないかどうかを検証する
strictEqual(検証値, 期待値, メッセージ) 検証値が期待値と同じ値であるかどうか検証する(===による比較)
notStrictEqual(検証値, 期待値, メッセージ) deepEqualメソッドの逆で、同じ値でないかどうかを検証する
deepEqual ( 検証オブジェクト, 期待オブジェクト, メッセージ) 検証オブジェクトと期待オブジェクトが同じ(同じキーと値ペアを持っている)かどうか、再帰的に比較して検証する
notDeepEqual ( 検証オブジェクト, 期待オブジェクト, メッセージ) deepEqualメソッドの逆で、同じでないかどうかを検証する
throw(関数, 期待する例外の型, メッセージ) 関数ないで期待する例外が発生するかどうかを検証する
表111-01 アサーションメソッド一覧

テスト結果ページ

 テスト結果ページはリスト111-03のように書きます。ポイントとしては次のとおりです。

HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>FizzBuzz Test</title>
  <!-- 1 QUnitテストレポートページ用CSSをインポート -->
  <link rel="stylesheet" href="css/qunit-1.10.0.css">
  <!-- 2 QUnitをインポート -->
  <script type="text/javascript" src="js/qunit-1.10.0.js"></script>
  <!-- 3 テスト対象コードをインポート -->
<script type="text/javascript" src="js/fizzbuzz.js"></script>
  <!-- 4 テストコードをインポート -->
<script type="text/javascript" src="js/fizzbuzz-test.js"></script>
</head>
<body>
  <!-- 5 テスト結果表示領域 -->
  <div id="qunit"></div>
</body>
</html>
リスト111-03 テスト結果ページ(qunit.html)

1 QUnitテスト結果ページ用CSSをインポート

 テスト結果を整形して表示するためのCSSをインポートします。

2 QUnitをインポート

 QUnit本体のjsファイルをインポートします。

3 テスト対象コードをインポート

 QUnitの後にテスト対象コードのインポート定義を追加します。

4 テストコードをインポート

 上述のテストコードのjsファイルを一番最後にインポートします。

5 テスト結果表示領域

 テスト結果を表示する領域として、idが“qunit”のdivタグをページに追加します。

 この15の記述の順番は必ず守るようにしてください。そうしないと正しくテストが行われません。

テスト実行結果

 ブラウザでテスト結果ページを開くと、記載したテストコードが実行され、テスト結果が表示されます(図111-01)。

図111-01 
図111-01 (再掲)

1 タイトル

 リスト111-03の<title>タグで指定した、テスト結果ページのタイトルが表示されます。クリックすることで、すべてのテストを再実行することができます。

2 ツールバー

 テスト実行を制御する項目が用意されています。表111-02にツールバーの機能を簡単にまとめます。

機能名説明
Hide passed tests チェックを入れると検証した結果エラーとならなかったテストケースを隠す(図111-02)
Check for Globals チェックを入れるとテストの中でグローバル変数を作成した場合に、そのテストケースをエラーとして扱う
No try-catch チェックを入れると、テストケース実行中に例外が発生が発生してもその例外をQUnitで表示しなくなる
Module: リスト111-02のmoduleメソッドで指定したグループを選択してテストを再実行する(図111-03)
表111-02 ツールバーの機能
図111-02 Hide passed tests表示の例
図111-02 Hide passed tests表示の例
図111-03 グループを選択してテスト再実行の例
図111-03 グループを選択してテスト再実行の例

3 ユーザエージェント

 テストを実行したブラウザのユーザエージェント情報が表示されます。

4 テスト結果概要

 テスト結果の概要として、実行時間とテストケース数(成功、すべて、失敗)が表示されます。

5 成功テストケース

 成功したテストケースは既定で閉じられた状態で表示され、リスト111-02にてmoduleメソッドで指定したテキストとtestメソッドで指定したテキスト、そしてテストケース内のアサーションメソッドの数(失敗、成功、すべて)が連結して表示されます。クリックすることで、実行したアサーションメソッドの結果が表示されます。また、「Rerun」リンクをクリックすると、テストを再実行できます。

6 失敗テストケース

 表示内容は成功テストケースを同じですが、既定で開かれた状態で表示されます。また、失敗したテストケースは赤で表示され、アサーションメソッドの結果が表示されます。アサーションメソッドの結果も色分けされ、成功したアサーションは緑、失敗したアサーションは赤で表示されます。

 ブラウザによっては、アサーションが失敗した原因となる行番号などの付随情報が表示されるものもあります(図111-04)。

図111-04 ブラウザよって付随情報が異なる例
図111-04 ブラウザよって付随情報が異なる例

※以下では、本稿の前後を合わせて5回分(第6回~第10回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。

6. [Sammy.js]URLによって処理を分割する

書籍転載の6本目(書籍内の番号は「77」)。URLの「#」以降の指定によって処理を分割することに着目したフレームワークである「Sammy.js」の基礎と基本的な使い方を紹介。

7. [Knockout]MVVMパターンでアプリケーションを構築する

書籍転載の7本目(書籍内の番号は「89」)。MVVM(Model-View-ViewModel)パターンをサポートするJavaScriptライブラリである「Knockout」の基礎と、基本的な使い方を解説。

8. 【現在、表示中】≫ [QUnit]テストコードを実行し、ブラウザで結果を確認する

書籍転載の8本目(書籍内の番号は「111」)。JavaScript用テストランナーの定番ライブラリである「QUnit」の基礎と基本的な使い方を説明。

9. [Underscore.js]さなざまなコレクション操作を行う

書籍転載の9本目(書籍内の番号は「100」)。ユーティリティ・ライブラリ「Underscore.js」の基礎として、さまざまなコレクション操作する方法を説明。

10. [Underscore.js]テンプレートとオブジェクトから文字列を生成する

書籍転載の10本目(書籍内の番号は「101」)。テンプレートとオブジェクトをバインドし、その結果を出力できる「Underscore.js」のテンプレートAPIの使い方を説明。

Twitterでつぶやこう!


Build Insider賛同企業・団体

Build Insiderは、以下の企業・団体の支援を受けて活動しています(募集概要)。

ゴールドレベル

  • 日本マイクロソフト株式会社
  • グレープシティ株式会社