読者です 読者をやめる 読者になる 読者になる

yutaponのブログ

javascript界隈の興味あるネタを備忘録的に残しておく場所

javascriptでテスト駆動開発 Mocha+expect.js+testem【前編】

JavaScriptのテストをするツール達

テスト駆動するときに必要なツールが2つあります。

テストフレームワーク

いわゆるxUnit系のツールがこれにあたります。
JavaScriptでの有名ドコロは下記のスライドが参考になります。
JS開発におけるTDDと自動テストツール利用の勘所

私はまだ2つしか使ったことがありません。

どちらもBDDライクな書き方で好きです。
特にMocha(モカと読みます)の方ですが、単体では使わず
should.jsやexpect.jsなどのアサーションライブラリと組み合わせて使います。
これはmocha単体のアサーションがないためです。
JasmineだとSinon.jsをセットでよく使います。

テストランナー

テストだけするなら必要ありませんが、テスト駆動をするなら必須です。
テスト駆動のフローは以下の通りになります。

  1. テストを書く
  2. テストが失敗することを確認する(REDを確認)
  3. 実装する
  4. テストを走らせテストが通ることを確認する(GREENを確認)
  5. リファクタリングする

テストランナーを使うと2と3の確認作業が楽になります。
テストの実行をテストランナーがしてくれるので、開発者はその結果を確認するだけで良くなります。

私が知っているテストランナーは3つしかありません・・・(本当はもっとあるはず)

Testem

ググってみるとたくさん紹介記事があります。
実際に導入も簡単で、特に悩むことはないと思います。

  • 特徴
    • ファイルの更新を検出して自動でテストを走らせる
    • 複数のブラウザを起動してテスト結果を表示できる
    • 事前処理、事後処理を記述できる(coffeeの事前コンパイルとか)
Karma(Testacular)

以前はTestacularという名前でしたがKarmaに変わりました。
比較的新しいランナーで、Google製です。

  • 特徴
    • Testemとほぼ同等
    • Require.jsを用いたテストに対応(Testemよりシンプル)
Grunt.js

Grunt.jsはJavaScriptのテストランナーではありませんが、
テストランナーとしても使えるので紹介だけ。
本当はGruntには違うことを任せて、JavaScriptのテストランナーとしては
使わないことが多いです。

  • 特徴
    • watchに指定したファイルに更新があればテストを実行する(というタスクを書ける)
    • タスクを作って自動コンパイルが得意(coffee, sass, less, stylus, jade, minify, concat, etc..)
    • Jenkinsと良い感じに連携できる

mocha + expect.js + Testem でnode.jsのテストする

今回はサーバーサイドのテストをしたいので、出力は全てターミナル上に表示するイメージで環境構築します。

テスト環境の構築

まずmocha, expect.js, testemをインストールします。

$ npm install -g mocha     // グローバルにインストール
...
$ npm install expect.js --save-dev
...
$ npm install -g testem
...

mochaコマンド、testemコマンドが実行できることを確認しておきます。

$ mocha --version
1.9.0
$ testem --version
0.2.94

テストケースを作る

とりあえずテスト対象のファイルと、テストコードを作成します。

$ mkdir lib     // テスト対象コードを置くディレクトリ作成
$ touch lib/calc.js
$ mkdir test    // テストコードを置くディレクトリ作成
$ touch test/calc.test.js
// lib/calc.js

// 足し算
exports.add = function(a, b){
  return a + b;
}
// test/calc.test.js

var expect = require('expect.js');
var calc   = require('../lib/calc.js');

describe('add', function(){
  it('1と1を与えたら2を返す', function(){
    var result = calc.add(1, 1);
    expect(result).to.be(2);
  });
});

mochaコマンドでテストが実行できることを確認してください。

$ mocha -R spec


  add
    ✓ 1と1を与えたら2を返す 


  1 test complete (9 ms)

mochaコマンドでテストを作れているのを確認できました。
次はこれをtestemに実行させます。

プロジェクトのルート直下にtestem.jsonを作ります。

{
  "framework": "mocha",
  "src_files": [
    "lib/*.js",
    "test/*.test.js"
  ],
  "launchers": {
    "Mocha": {
      "command": "mocha test/*.test.js -R tap",
      "protocol": "tap"
    }
  },
  "launch_in_dev": [
    "Mocha"
  ]
}

testemを実行します。
testemを実行すると、ターミナルの画面を占有するので、
新しいターミナルウインドウを立ちあげて実行するのがおすすめです。

$ testem

テストが実行されたと思います。
これでファイルを編集した瞬間、testemがテストを走らせるので
バグに気づきやすくなります。

終わりに

calcというファイルを作っておきながら足し算しか作ってません。
それにこのadd関数はたくさんのバグを含んでいます。
また、今回はサーバーサイドのコードを対象としましたが、
フロント特有のテストの仕方があったりします。
というわけで、次回に続きます。