QUnitの最も基本的な使い方

前回の続き。

テスト駆動開発の考え方は、なんとなく分かった。
だが、具体的なことはまだ何も分かっていない。
その考え方をどのように実現するのか、という部分。
テスト駆動開発の考え方は分かったし、本当にそれが実現できるなら素晴らしいと思う。だが本当にそんなことを出来るのだろうか。

本当に、自動でテスト出来るのか?
本当に、リグレッションを防止できのか?
机上の空論ではなく本当に、メリットを享受できるのか。

ということで、JavaScriptのテスティングフレームワークを実際に使ってみる。

QUnitの準備

今回はQUnitを使うことにした。

ざっと調べたところ、後発のmochaなどのほうがいいらしいが、さっぱり理解できなかった。
Node.jsが前提になっているような記事も多く、今の自分には無理だと判断。
背伸びせず、簡単、シンプルだとされているQUnitにした。

QUnitはもともとjQueryのテストのために開発されたそうだが、現在はjQueryとは無関係に使用できる。

必要なJavaScriptファイルとCSSファイルをCDNで読み込む。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>QUnit</title>
  <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.22.0.css">
</head>
<body>
  <div id="qunit"></div>
  <div id="qunit-fixture"></div>
  <script src="http://code.jquery.com/qunit/qunit-1.22.0.js"></script>

  <script src="test.js"></script>

</body>
</html>

これで利用できる。後は、テスト用のJavaScriptファイル(上記の例だとtest.js)に、内容を書き込んでいけばいい。

QUnitの使い方

testという関数で記述し、第一引数にそのテストケースの名前、第二引数に内容を書く。

最も基本的な書き方

testの第二引数の無名関数のなかに、ok関数を書く。
その第一引数に、確認するコードを書く。
第二引数に、ブラウザに表示させるメッセージを書く。

ok関数は、第一引数の値がtrueであるかを判定するための関数。

test("okの挙動を確かめるテスト", function() {
  ok(false, "falseのok関数");    // テストは通らない
  ok(true, "trueのok関数");      // テストが通る
  ok(1 === '1', "同値演算子のok関数");      // テストは通らない
  ok(1 == '1', "等価演算子のok関数");       // テストが通る
});

上記の内容を実行すると、ブラウザにこのように表示される。

f:id:numb_86:20160326174517p:plain

なお、testやokの前にQUnit.をつけても動く。名前空間の汚染を考えれば、このほうがよさそうだ。以下、この書き方で統一していく。

// 先ほどと全く同じ結果になる
QUnit.test("okの挙動を確かめるテスト", function() {
  QUnit.ok(false, "falseのok関数");  // テストは通らない
  QUnit.ok(true, "trueのok関数");        // テストが通る
  QUnit.ok(1 === '1', "同値演算子のok関数");        // テストは通らない
  QUnit.ok(1 == '1', "等価演算子のok関数");     // テストが通る
});

equal,deepEqua,throws

ok関数は、アサートの一種だという。 アサート、というのがよく分からないが、条件や要件のことだろう。

QUnitには、ok以外にもいくつかアサートがある。

equal関数は、第一引数と第二引数の値が一致するか判定する。第三引数にメッセージ。
第一引数にチェックすべき値を入力し、期待される結果を第二引数に入れる。
比較は、等価演算(自動で型変換をする)で行う。同値演算(型変換をしない)は、strictEqual関数で行う。

QUnit.test("テスト", function() {
  // 以下は通る
  QUnit.equal(false, false, "equal関数");
  QUnit.equal(33, 33, "equal関数");
  QUnit.equal(1, '1', "equal関数");

  // 以下は通らない
  QUnit.equal(0, '3', "equal関数");
  QUnit.equal(33, 34, "equal関数");
  QUnit.strictEqual(1, '1', "strictEqualequal関数");
});

deepEqual関数は、オブジェクトや配列を比較する。
内容が完全に一致していないと、通らない。

QUnit.test('名前', function(){
    var obj1 = { foo: "bar" };
    QUnit.deepEqual(obj1, { foo: 'bar' }, "最初のアサート");   // 通る
    obj1.hoge = 'hoge';
    QUnit.deepEqual(obj1, { foo: "bar" }, "2回めのアサート");    // 通らない
    QUnit.deepEqual(obj1, {  // 通る
        hoge: "hoge",
        foo: "bar"
    }, "3回めのアサート");
});

throws関数は、第一引数に渡した関数が例外を投げるかどうかを調べる。

QUnit.test('throws', function(){
    QUnit.throws( function(){ throw 'error' }, 'アサート' ); // 通る
    QUnit.throws( function(){}, 'アサート2' ); // 通らない
});

stopとstart

test関数のなかでstop関数を使うと、処理を停止できる。その後、start関数を使うことで、処理が再開される。
下記の例だと、テスト関数開始の2秒後に、ok関数が実行される。

QUnit.test("stop", function() {
  QUnit.stop();
  setTimeout(function(){
    QUnit.start();
    QUnit.ok(1 == "1", "stopのテスト");
  }, 2000);
});

この例だと何の意味もないが、例えば、非同期処理のテストなどで、すぐにはアサートを実行したくない、コールバックの処理が終わってからテストしたい、という状況などで利用できる。

参考:QUnitの概要 - Qiita