datchの日記

気がついたら社会人。気になる技術的なことについて少しずつ書いていけたらと思っております。

Javascriptテストフレーム Mochaを触ってみた

内定先のインターンのお手伝いしていますが、皆さんがアイディア出しに躓いているのを見ると、やはりサービスを作ることは大変だと実感している最中です。
今回はJavascript用テストフレームワークの「Mocha」を紹介したいと思います。

Mocahとは?



Javascript用テストフレームワーク

BDD?TDDじゃなくて?



自分も初めて聞いた単語なので、腹落ちするために色々とネットで検索してみた。

プログラム開発手法の一種で、テスト駆動開発から派生した物である。

テスト駆動開発で記述されるテストケースは、作成したプログラムの動作が正しいかどうかを検証するために行う「テスト」である。テストであるという点は同一であるが、加えて、これから作成しようとするプログラムに期待される「振る舞い」や「制約条件」、つまり「要求仕様」に近い形で、自然言語を併記しながらテストコードを記述する。テストフレームワークメソッド名も自然言語(英語など)に近い形をとっている。
テストコードの可読性があがる上、テストコードが要求仕様となりうる。要求仕様からテストコードを起こすさいも、スムーズにコードに移行しやすい。
BDDではスペック(仕様)とテストは限りなく近い物である。従って、テスト駆動開発における「テストファースト」は、BDDにおいては「スペックファースト」となり、スペックを作ってから実装するという、より自然な形でのプログラム製作を実現している。
いくつかのテストフレームワークは、

  1. アプリケーションの振る舞いを記述するストーリーフレームワーク
  2. オブジェクトの振る舞いを記述するスペックフレームワーク

の2種類を含む。

Wikipediaを参照に

他のサイトも色々と調べてみましたが、TDDでは機能毎にテストを行い(単体テスト)、BDDではそのひとつ上のレイヤーでテストを行うという記述が多かったです。
後述するチュートリアルでは、機能単体でテストが行うことで仕様が満たされているかを確認する手法です。BDDについてはテストする処理の振る舞いについて記述し、他のモジュールとも合わせ行えてテストする(例えば、ログイン処理)といった感じです。*1

チュートリアル



そろそろnpmするだけの導入節も面白く無いのでこっちでまとめてしまおう。

インストール
$ npm install -g mocha
$ mocha --version # バージョンが表示されればおk
1.21.4
簡単なテスト

まずは公式サイトチュートリアルのコードをそのまま実行してみる。

test.js

var assert = require("assert");
describe('Array', function(){
  describe('#indexOf()', function(){
    it('should return -1 when the value is not present', function(){
      assert.equal(-1, [1,2,3].indexOf(5));
      assert.equal(-1, [1,2,3].indexOf(0));
    });
  });
});

このコードをテストで実行してみる。

$  mocha

  .

  ✔ 1 test complete (1ms) 

テストの説明を見ると、-1を返さなければならない、と書いてある。
まずは簡単にテストコードの中身を覗いてみる。

assert.equal(-1, [1,2,3].indexOf(5));
assert.equal(-1, [1,2,3].indexOf(0));

indexOf()は指定された要素数を返し、なければ-1を返す関数だ。
配列の内容は[1,2,3]で5と0の要素があるかをそれぞれ問い合わせている。
もちろん配列の中身に無いので、どちらも-1を返すのが正しい振る舞いなので、正常値は-1に設定してある。
テストを実行して成功したのが確認できた。

また、同様のテストだが以下のように異なる書き方も出来る。
ちなみにこの書き方では 'should' パッケージが必要なので事前に以下のパッケージをインストールしておこう。

>|bash|
$ npm init
何か聞かれるがEnterを連打で問題ない
$ npm install should

|

var should = require('should');
describe('Array', function(){
  describe('#indexOf()', function(){
    it('should return -1 when the value is not present', function(){
      [1,2,3].indexOf(5).should.equal(-1);
      [1,2,3].indexOf(0).should.equal(-1);
    });
  });
});

mochaの機能紹介



mochaには様々な関数があるので、ここで取り上げてみる。

describe

この関数にはグルーピングを行いたい範囲とその説明を記述する

describe('Userのテスト', function()
{
  // ここにテストの詳細について記述する
});
it

この関数にどのような振る舞いをテストするのかを記述する。

describe('Userのテスト', function()
{
  // ここにテストの詳細について記述する
  describe('パスワード', function()
  {
    it('パスワードがsha256でハッシュ化されている', function(done)
    {
      // 振る舞いについて記述する
    });
  });
});
assert

mocha自体の関数ではないが、assertを検知することでMochaはテストを行う。

describe('Userのテスト', function()
{
  var user = new User('password');
  // ここにテストの詳細について記述する
  describe('パスワード', function()
  {
    it('パスワードがsha256でハッシュ化されている', function(done)
    {
      assert('5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8', user->passwordHash);
    });
  });
});
before, after, beforeEach, afterEach
  1. before : テストを開始前に実行する
  2. after : テストを終了後に実行する
  3. beforeEach : テスト毎に開始前に実行する
  4. afterEach : テスト毎に終了前に実行する
describe('Userのテスト', function()
{
  before(function()
  {
    var user = new User('password');
  });

  describe('パスワード', function()
  {
    it('パスワードがsha256でハッシュ化されている', function(done)
    {
      assert('5E884898DA28047151D0E56F8DC6292773603D0D6AABBDD62A11EF721D1542D8', user->passwordHash);
    });
  });

  after(function()
  {
    user = null;
  });
});

最後に



やはりJavascriptのテストツールですが、これだけだとTDDとBDDとの違いがいまいちわからないですね。
MochaではTDDも行えるので、teardonw()などのPHPUnitなどで見る関数も使用出来ます。
フロントエンドもテストが行えるようになり、様々な環境が揃ってきたので、素早く、品質の高い開発が行えそうですね。

*1:実際の業務などでTDDを使って開発を行っていないので、この記述はかなりあやふやな感じですが