Attention! Translated article might be found on my English blog.

2015年11月20日金曜日

mochaでCoffeeScriptクラスのロジックユニットテストをしてみた際のメモ

ログ代わりなので読みづらいと思います。

いちいちブラウザでHTMLを開くのが辛くなってきたのでユニットテストを書くことにしました。
テストフレームワークにはnode.jsモジュールのmochaを使いました。
ひとまずchaiは使わず、mochaでやれるところまで書いてみます。

なお、環境はMac OS X 10.11, node.js v0.12.4, CoffeeScript 1.9.1です。

インストローリング

$ npm install mocha
mocha@2.3.4 ../../../../node_modules/mocha
├── escape-string-regexp@1.0.2
├── supports-color@1.2.0
├── growl@1.8.1
├── commander@2.3.0
├── diff@1.4.0
├── debug@2.2.0 (ms@0.7.1)
├── mkdirp@0.5.0 (minimist@0.0.8)
├── jade@0.26.3 (commander@0.6.1, mkdirp@0.3.0)
└── glob@3.2.3 (inherits@2.0.1, graceful-fs@2.0.3, minimatch@0.2.14)

セットアッピング

mochaコマンドへのパス
mochaへのパスが通ってなかったので~/.bash_profileに以下の行を追加し、source ~/.bash_profileした。

# ~/.bash_profile
export PATH=$PATH:$HOME/node_modules/mocha/bin

Better CoffeeScript Testing With Mocha - Envato Tuts+ Code Tutorialを参考にテストコードを作成。

テスト用ファイルの場所
mochaコマンド実行時はtestというディレクトリ内にテスト用coffeeファイルが必要な模様。
testディレクトリが無いと以下のようにエラーが出てしまった。

$ mocha
/path/to/node_modules/mocha/lib/utils.js:626
        throw new Error("cannot resolve path (or pattern) '" + path + "'");
              ^
Error: cannot resolve path (or pattern) 'test'

多分ディレクトリは指定できると思われるがひとまずtest内にファイルを置くことにした。

mochaコマンドオプション
上記サイトを参考にテスト用coffeeファイル内でrequireを使ったところ、

$ mocha --compilers coffee:coffee-script
/path/to/node_modules/coffee-script/lib/coffee-script/coffee-script.js:210
          throw new Error("Use CoffeeScript.register() or require the coffee-s
                ^

Error: Use CoffeeScript.register() or require the coffee-script/register module to require .coffee.md files.

てな感じでエラーが出てしまったので、実行時には

$ mocha --compilers coffee:coffee-script/register

とすることでエラーを回避できた。
参考: Fixed Mocha for CoffeeScript 1.7+ and Travis CI errors by MrSaints · Pull Request #6 · github/generator-hubot · GitHub

クラスファイル側の修正
別のjsファイルからも使えるように、Hoge.coffeeには

window.Hoge = Hoge

と記述していたのだが、このwindowがユニットテスト時には存在しないようで

$ mocha --compilers coffee:coffee-script/register
/path/to/project/coffee/Hoge.coffee:68
  window.Hoge = Hoge;
  ^
ReferenceError: window is not defined

というエラーが出てしまった。
windowの代わりにthisとすることでエラーを回避し、ユニットテストとブラウザの両方で利用できるようになった。
参考: FreePender: JavaScript Unit Testing with Mocha

テストライティング

HogeクラスのクラスメソッドmakeHogeをテストするコードだけ作ってみた。
ひとまずtest/HogeTest.coffeeを以下のように書くことでユニットテストを正常に実行することができた。

assert = require 'assert'
{Hoge} = require '../Hoge.coffee'

describe 'Hoge instance', ->
    range1 = range2 = null
    it 'should make correct Hoge instance', ->
        range1 = Hoge.makeHoge 5, 10
        assert(range1.location == 5)

        assert(range1.length == 10)

assertの代わりにchaiのshouldなどを使うとベターらしい。今後の課題とする。

エグゼキューティング

$ mocha --compilers coffee:coffee-script/register


  Range instance
    ✓ should make correct Range instance



  1 passing (12ms)

ユニットテストを実行し、メソッドが意図通り動いていることを確認できたので今回はここまで。
最終的にファイル配置は以下のような感じ。srcディレクトリを切ったほうがいいかも。
project
|- index.html
|- script.js
|- jquery.js
|- coffee
   |- Cakefile
   |- Hoge.coffee
   |- App.coffee
   |- test
      |- HogeTest.coffee

今後は
・テストファイル分割時の挙動
・クラスが別のクラスに依存性している場合のテスト
・cakeでの自動化
などを試してみたいと思います。