北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

QUnitでJSのテストを書いてみた

JSでテストファーストしたかったので、QUnitを試してみました。QUnitを使えば、とても簡単にJavaScriptのテストスイートを作ることができ、オススメです。

てっとり早く試す

インタネットにつながる環境であれば、てっとり早くQUnitを試せます。

QUnitのページに行って、View Sourceタブに表示されているHTMLをコピペしてローカルに保存します*1。このHTMLをブラウザで開けば、サンプルのテストが走ります。4つのテストがあって、4つ目だけfailed(赤文字表示)となればうまく動いてます。

QUnitでは、このようにブラウザでテストの結果を確認します。緑帯が表示されればOKで、赤帯が表示されればNGです。

もうちょっとまともに使う

インストール

最初の例ではネットワーク上のリソースを使ってましたが、まともに使うときはローカルにファイルを揃えましょう。

  1. HTMLを用意 (「てっとり早く試す」を参照)
  2. jQuery をDL し、jsファイルを設置
  3. testrunner.js をDL し、jsファイルを設置
  4. testsuite.cssをDL し、cssファイルを設置
  5. 1. のHTMLの scriptタグとlinkタグを編集し、 2、3、4 で設置したjsとcssを読むようにする
テストの書き方

まず、上記手順で得られるHTMLの書き方はちょっと使いにくいので、HTMLを編集して使い勝手を改善します。

  1. testrunner.js の読み込みを上部に持って来て、テストスクリプトより先に読み込ませる*2
  2. 1.によってテストスクリプト内の $(document).ready(function(){ ... }); は不要になるので外す *3

テストは、以下のように書きます。

  1. HTML側に、テストしたい *.jsを インクルードする
  2. <script>内か、もしくは外部の*.jsにテストを書く*4
  3. テストスクリプトは、module(モジュール名); で始める *5
  4. test関数で、テスト用の関数を追加する(複数個追加していい)
  5. 各テスト用の関数の先頭で、expect関数でテストの数を指定する(省略可)
  6. 各テスト用の関数内で、ok、equals、same でテストする
  7. テストでhtmlを使うときは、#main 内に部品を置いておく *6 *7

こんな感じです。SCRIPTタグの中身は、適時外部のjsにした方がベターです。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 
                    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<title>QUnitのテストのサンプル</title>
<link rel="stylesheet" href="testsuite.css" type="text/css" media="screen" />
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="testrunner.js"></script>

<script>
/* テストしたいコード(1)。普通は外部のJSのはず。 */
function sum(n1, n2){
    return n1 + n2;
}
function even(n){
    return n % 2 == 0;
}
</script>

<script>
/* テストしたいコード(2)。普通は外部のJSのはず。 */
function getTestValue(){
    return document.getElementById("test-value").innerHTML;
}
</script>

<script>
/* テストコード(1)。外部JSにするとよい */
module("Module1");
test("test sum() function", function () {
    expect(3);
    equals(sum(2,3), 5, "2+3");
    equals(sum(4,0), 4, "4+0");
    equals(sum(1,-5), -4, "1-5");
});
test("test even() function", function () {
    expect(3);
    ok(! even(1), "1 is odd");
    ok(even(2), "2 is even");
    ok(even(0), "0 is even");
});
</script>

<script>
/* テストコード(2)。外部JSにするとよい */
module("Module2");
test("test getting value", function () {
    expect(1);
    equals(getTestValue(), "TEST");
});
</script>
</head>

<body>
<h1>QUnitのテストのサンプル</h1>
<h2 id="banner"></h2>
<h2 id="userAgent"></h2>
<ol id="tests"></ol>
<div id="main" style="display: none;">
  ここはテストに使うHTML。毎回リセットされる。
  <span id="test-value">TEST</span>
</div>
</body>
</html>

*1:このHTMLはDLできないっぽい。

*2:jquery.jsのincludeの直後でよい。

*3:test()関数がやってくれます

*4:jQuery内でのQUnitの使い方を見ると、全て外部のjsファイルにテストを書いてincludeしている

*5:module関数には二つの役割がある。(1)テスト中にモジュール名を表示 (2)setupとteardownの関数をリセットしてくれる

*6: #main内に書いたHTMLは、各テスト関数が終わるごとにリセットされる。

*7:styleでdisplayをnoneにしとくと、ゴミが見えなくて気分がいいかもしれません