スポンサーリンク

今から3分で qUnit の使い方を身に付ける (JavaScriptの単体テスト)


qUnitは,JavaScriptコードを単体テストするためのライブラリ。

qUnitはjQueryプロジェクトから派生して誕生した。jQueryを使わない普通のコードであっても,回帰テストの対象にできる。


このテストツールの初歩を,今から3分で習得するための記事。





たった3分なので集中されたい。


(2) テスト対象

前項のダウンロード完了を待たずに,作業フォルダに新規HTMLファイルを作る。

テスト対象として,かんたんなコードを用意する。下記の内容をコピペしてtest.htmlで保存。

<html>
<body>

<script language="JavaScript">

// テストしたい自作モジュール

var math_obj = {
	// 2乗
	square : function ( x ){ return x*x; },
	// 3乗
	cube   : function ( x ){ return x*x; } // 意図的なエラー
};

</script>


</body>
</html>


数学計算のモジュールである。これをテスト対象とする。

2乗と3乗の関数が含まれている。
しかし,3乗のほうは中身が間違っているのを目視で確認する。(恐らく3乗を作るために2乗の行をコピペして,そのまま補正を忘れてしまったのだろう。)

ここまでで1分。


(3) テストコード

前項のHTMLの最後の部分の,</body>の直前の箇所に,テストコードを追加する。


該当箇所に下記をコピペ。


<!-- QUnit ここから -->

<script src="jquery-1.2.6.min.js"></script>
<script src="testrunner.js"></script>
<link rel="stylesheet" href="testsuite.css" type="text/css" />
<script language="JavaScript">


// テストコード

module("数学");

test("2乗", function() { // 2乗関数に関するテスト
	equals( 1, math_obj.square(1) );
	equals( 4, math_obj.square(2) );
	equals( 1, math_obj.square(-1) );

	expect( 3 ); // テスト総数
});

test("3乗", function() {
	equals( 1, math_obj.cube(1) );
	equals( 8, math_obj.cube(2) ); // これはエラーになる

	expect( 3 ); // これもエラーになる
});

// テストコード終了


</script>

<!-- 結果表示部 -->
<div>
	<h1>QUnit test execution</h1>
	<h2 id="banner"></h2>
	<h2 id="userAgent"></h2><!-- ユーザエージェント -->
	<ol id="tests"></ol><!-- 実行情報 -->
	<div id="main"></div><!-- サマリ -->
</div>

<!-- QUnit ここまで -->


上記のコード中で,

  • module("数学") : テスト対象のモジュールを宣言。
  • test("2乗", function() { 〜 }) : テスト内容を宣言。
  • equals( 期待値, 実行値 ) : 実行結果が思い通りの値かどうかをチェック
  • expect( 数 ) : test() 内で,何個のチェックが実行されるか(テスト総数)を宣言。

という意味である事を理解する。
1:45。


(4) 実行(1度目)

前項のHTMLをブラウザで開く。

すぐにテスト実行され,実行結果が2つ出てくる。ユーザエージェントと実行時間も表示される。



1つ目の2乗関数の結果は,緑色。クリックで詳細が表示される。

数学 module: 2乗 (0, 3, 3)

数字は,エラー・成功・総数を表す。エラー0個なので,この関数のテストはOK。



3乗関数の結果は,赤色。

数学 module: 3乗 (2, 1, 3)

エラー2個。クリックでエラー箇所を調査

1. okay: 1
2. failed expected: 4 actual: 8 (8を期待したのに4だった)
3. Expected 3 assertions, but 2 were run (3つのチェックを期待したのに2つしか実行されていない)

(5) 修正

テスト結果を見て,コードを修正しよう。(やってみてください)




具体的には,まず自作した数学モジュールの3乗関数を

	// 3乗
	cube   : function ( x ){ return x*x*x; }

のように直す。これでequals( 8, math_obj.cube(2) );をクリアできる。

そして,3乗関数のテスト中で,チェック回数をもうひとつ増やしてみる。

	equals( -1, math_obj.cube(-1) );

のように。これでexpect(3)をクリア。


(6) 実行(2度目)

ブラウザで開きなおす。

今度はオールグリーンで,タイトル下のバナー部も緑色になる。単体テストとその対応が終了した。




ダウンロード開始からテスト対応終了まで,私は 2:18 かかりました。

目標

3分間かけて,qUnitの使い方として

  • test() の中には,いくつかのテストのまとまりを記述する。
  • equals() で値の比較ができる。
  • テスト結果はブラウザで閲覧し,だめだった箇所を特定する。

という点を理解すればOK。

解説

かんたんな自作関数をqUnitフレームワークの単体テストにかけ,結果を分析し,修正作業を行なった。

今回はテスト対象のコードもテストコードも,いずれもHTML内に直接記述したが,もちろん外部ファイルで分離してもよい。

1行で1テスト書けるので,手軽にテスト駆動開発を行なう事ができる。

Tips (1) DOM操作を含むようなコードをテストする

HTML要素を操作する場合,かんたんなケースであれば,操作対象の下に直接テストコードを埋め込んで実行する事もできる。


たとえば,下記のように。

<html>
<body>

<br><br>

これはテストを行うための画面です。

<br><br>

<input type=text id="my_text1">
<input type=text id="my_text2">
<input type=text id="my_text3">

<br><br>

<script language="JavaScript">

// 自作モジュール

var dom_obj = {
	// 全ボックスに書き込み
	fill  : function(){
		$( "input[id^='my_text']" ).each(function( i ){
			this.value += i + "番目";
		});
	},
	// 全ボックスから消去
	clear : function(){
		$( "input[id^='my_text']" ).each(function(){
			this.value = "";
		});
	}
};

</script>



<!-- QUnit ここから -->

<script src="jquery.js"></script>
<script src="testrunner.js"></script>
<link rel="stylesheet" href="testsuite.css" type="text/css" />
<script language="JavaScript">

// テストコード

module("DOM操作");

test("1回書き込み後消去", function() {
	dom_obj.clear();
	dom_obj.fill();
	$( "input[id^='my_text']" ).each(function(i){
		equals( i + "番目", this.value );
	});
	dom_obj.clear();
	$( "input[id^='my_text']" ).each(function(i){
		equals( "", this.value );
	});

	expect( 6 );
});

test("2回書き込み", function() {
	dom_obj.clear();
	dom_obj.fill();
	dom_obj.fill();
	$( "input[id^='my_text']" ).each(function(i){
		equals( i + "番目", this.value );
	});

	expect( 3 );
});


// テストコード終了

</script>
<div>
	<h1>QUnit test execution</h1>
	<h2 id="banner"></h2>
	<h2 id="userAgent"></h2><!-- ユーザエージェント -->
	<ol id="tests"></ol><!-- 実行情報 -->
	<div id="main"></div><!-- サマリ -->
</div>

<!-- QUnit ここまで -->

</body>
</html>

DOM操作を行なうような自作モジュールについて,そのテストを実行する。

「QUnit ここから」以降の部分は,テスト用のコードである。



上記のテストケースを実行すると,「1回書き込み後消去」というテストは成功する。

しかし,「2回書き込み」のほうはエラーが出る。

fill()関数の実装が「テキストボックス内の既存の文字列に追加する」という仕様であったため,「〜番目」の文字列が2個連続して出力されてしまうのだ。

なので,ここではfill()の中味を += ではなく

			this.value = i + "番目";

のように = に変更すればよい。

その後,ブラウザをリロードすればテストは通る。


Tips (2) 別ウィンドウでテストする


ページの構成上同じウィンドウ内でテストするのには限界がある,と感じた場合,別ウィンドウでテスト実行することもできる。

下記記事では,そのための関数が公開されている。

JavaScriptで単体テストをするならQUnitはいかが?


HTMLエレメントに対するQUnitテストコードを書いてみる
http://hisasann.com/housetect/2008/09/javascriptqunit




jQuery公式サイトには,qUnitのドキュメントとサンプルがあるのでそちらも参照できる。

DOCUMENTATION - QUnit
http://docs.jquery.com/QUnit


ちなみに,「qUnit ソフトウェア 結果」などでグーグル検索すると,「株式会社くいんと」という全く関係ないサイトが一番上に出てくるので注意。
nとiが逆だ。


Quint 製品情報
http://www.quint.co.jp/jp/pro/vox/index.htm