今から3分で qUnit の使い方を身に付ける (JavaScriptの単体テスト)
qUnitは,JavaScriptコードを単体テストするためのライブラリ。
qUnitはjQueryプロジェクトから派生して誕生した。jQueryを使わない普通のコードであっても,回帰テストの対象にできる。
このテストツールの初歩を,今から3分で習得するための記事。
たった3分なので集中されたい。
(1) DL
作業ディレクトリに以下の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