ズッキーニのプログラミング実験場

プログラミング + アカデミック + 何か面白いこと。 記載されているものは基本的に私が所属する団体とは関係がありません。

   Jul 20

Mocha と Chai による ブラウザサイド単体テスト – 環境構築からjQuery Deferredまで –

by zuqqhi2 at 2015年7月20日
Pocket

 MochaChaiを使ってブラウザサイド単体テストをやってみる。
この記事では環境構築、同期処理のテスト、非同期処理のテスト、jQuery Deferredのテストの基本のみ扱う。

環境

  • OS
    • Windows 7 Enterprise SP1
  • Mocha
    • 2.2.5
  • Chai
    • 3.1.0
  • jQuery
    • 2.1.4

環境構築

 本記事では、Mocha、ChaiやjQueryをCDNから直接使うため、特に何かをダウンロードする必要はなく、
例えば以下のようなディレクトリ構成で各ファイルを作成すれば大丈夫。

.
├── spec
│   ├── main_spec.js
│   └── spec_runner.html
└── src
    └── main.js

2 directories, 3 files

同期処理のテスト

 ものすごく単純に下記の関数をテストする場合を考える。

function double(n) {
  if(!n) {
    throw new Error("no param");
  } else {
    return n * n;
  }
}

 この関数に対するテストコードはBDDスタイルで下記のように書ける。

describe('SampleTest', function(){

  describe('Test Double Func', function(){
    it('should return double value', function(){
      expect(double(2)).to.equal(4); //except assertion
      double(3).should.equal(9); //should assertion
    });

    it('should throw error undefined without param', function(){
      expect(function() { double() }).to.throw("no param");
    });

  });

});

 ブラウザで単体テストを実行させるにはspec_runnerというHTMLファイルを作成する必要がある。
この中で、mocha・chaiや先ほど作成したmain.jsとmain_spec.jsを読み込む。
mocha・chaiの設定もここに記載する。

<html>
<head>
  <meta charset="utf-8">
  <title>Mocha Tests</title>
  <link href="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel="stylesheet" />
</head>
<body>
  <div id="mocha"></div>
  
  <script type="text/javascript" src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.1.0/chai.js"></script>

  <script>
    mocha.setup('bdd')
    var assert = chai.assert;
    var expect = chai.expect;
    chai.Should();
  </script>
  
  <script src="../src/main.js"></script>
  <script src="./main_spec.js"></script>
  
  <script>
    mocha.checkLeaks();
    mocha.run();
  </script>
</body>
</html>

 main.js、main_spec.js、spec_runner.htmlの3つのファイルが作成できたら、
spec_runner.htmlをダブルクリックで起動して結果を確認する。
以下のような画面になっていたら、テストをパスしたことになる。
失敗する場合は赤文字で各ケースの下にエラーメッセージが表示される。
main_spec1

非同期処理のテスト

 javascriptではコールバックを含む処理が頻出する。
そういった関数をテストする場合は下記のようにすれば良い。

function doubleAsync(n, callback) {
  setTimeout(function(){
    callback(n * n);
  }, 100);
}
describe('Test DoubleAsync Func', function(){
  it('should return double value', function(done){
    doubleAsync(2, function(result){
      result.should.equal(4);
      done();
    });
  });
});

 非同期処理に対するテストコードではdoneが必須である。
これを忘れると永久に処理は終わらない。
 spec_runner.htmlは変更する必要はない(ファイル名を変更した場合は、読み込むファイル名を変更する必要がある)。
 先ほどと同じようにダブルクリックでspec_runner.htmlを起動すると今度は以下のように、かかった時間が表示される。

main_spec2

jQuery Deferred

 jQuery Deferredを使った場合も基本的には非同期処理と同じようにすればいい。
テスト対象のコードとして今度は以下の様な関数を考える。

function api_data() {
  var deferred = jQuery.ajax({
    url: "https://app.rakuten.co.jp/services/api/IchibaItem/Search/20140222?format=json&keyword=%E6%A5%BD%E5%A4%A9&genreId=559887&shopCode=rakuten24&applicationId=#{Please input your id}",
    dataType: "jsonp"
  })
  .done(function(items) {})
  .fail(function(error) {})

  return deferred;
}

 これは楽天商品検索APIの結果を取得するコードである。この関数をテストする場合は以下のようにalwaysを使えば良い。

describe('SampleTest', function(){

  describe('API Data Func', function(){

    it('should return correct dada', function(done){
      api_data().always(function(result) {
	expect(result['page']).to.equal(1);
        done();
      });
    });

  });

});

 jQueryを読み込む必要があるため、spec_runner.htmlを以下のように変更する。

<html>
<head>
  <meta charset="utf-8">
  <title>Mocha Tests</title>
  <link href="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.css" rel="stylesheet" />
</head>
<body>
  <div id="mocha"></div>
  
  <script src="https://cdn.rawgit.com/jquery/jquery/2.1.4/dist/jquery.min.js"></script>
  <script type="text/javascript" src="https://cdn.rawgit.com/mochajs/mocha/2.2.5/mocha.js"></script>
  <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.1.0/chai.js"></script>

  <script>
    mocha.setup('bdd')
    var assert = chai.assert;
    var expect = chai.expect;
    chai.Should();
  </script>
  
  <script src="../src/main3.js"></script>
  <script src="./main_spec3.js"></script>
  
  <script>
    mocha.checkLeaks();
    mocha.globals(['jQuery*']);
    mocha.run();
  </script>
</body>
</html>

 mocha.globalsの”jQuery*”がポイント。これがないとたとえば以下のようなエラーが出てしまう。

main_spec3_error

 Mochaに対してグローバル変数名をあらかじめ提示しないとエラーになってしまう。
今回のコードで利用しているグローバル変数は”jQuery”とjsonpで利用する”jQuery[0-9]+”である。
jsonpで利用する方は毎回番号が変わってしまうため、両方指定するには”jQuery*”とする必要がある。
 正しく設定すれば以下のような結果になる。

main_spec3

Related Posts

Pocket

You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.