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

2015年11月24日火曜日

mocha+jsdom+coffeescriptでクライアントサイドjsをユニットテストする

あくまで初心者の備忘録なのでご注意ください。

経緯
mochaでのcoffeescriptのテストに関してはmochaでCoffeeScriptクラスのロジックユニットテストをしてみた際のメモCoffeeScriptのユニットテストでassertからchaiに変更する書いた。
その後実装を進めていくと、jQueryやwindowにアクセスしている箇所をテストしようとするとエラーが出てテストできなかった。

jasmine, phantomjsなどを検討したが、自分の環境では今ひとつ解決できなかった。

最終的にjsdomを使い、テスト用コード実行前にwindowとjQueryオブジェクトを作ることで無事テストできるようになった。

テスト手順
以下、テスト手順ごとに必要な作業や修正箇所を解説する。
まずテスト手順自体は以下の通り。

1: cake buildで従来通りクラスごとに分割したcoffeescriptを1つのjsファイルにまとめる。
2: cake buildtestで手順1のファイルとテスト用jsファイル(windowと$を設定するためのコード)を結合してテスト用ファイルとして書き出す。
3: cake testでテストを実行する。

1: cake buildで従来通りクラスごとに分割したcoffeescriptを1つのjsファイルにまとめる。
これは過去に書いた方法と同じ。

2: cake buildtestで手順1のファイルとテスト用jsファイル(windowと$を設定するためのコード)を結合してテスト用ファイルとして書き出す。

手順2のテスト用jsファイルとして、以下のようなコードをTestWindow.jsとしてtestディレクトリに入れた。

unction SetupTestWindow() {
    var jsdom = require('jsdom').jsdom;
    var markup = '<html><body><h1 class="example">Hello World!</h1><p class="hello">Heya Big World!</body></html>';
    var doc = jsdom(markup);
    var w = doc.parentWindow;
    $ = require('jquery')(w);
    window = w;
}
SetupTestWindow();

このファイルと手順1のファイルをcatして出力するタスクをCakefileに追加した。
タスクのコードは以下のとおり。

task 'buildtest', 'compile test files', ->
    targetList = ['test/TestWindow.js', '../script.js']
    targetList = targetList.join(' ')

    cmd ="cat #{targetList} > ./test/test.js"

    exec cmd, (error, stdout, stderr) ->

        util.log(error) if error
        util.log(stdout) if stdout
        util.log(stderr) if stderr

見るとわかる通り、cake buildtestを実行するとtestディレクトリ内にtest.jsが作成される。

3: cake testでテストを実行する。
testタスクは単純にmocha --compilers coffee:coffee-script/registerするだけになっている。

手順3で実行するのは前回同様テスト用のcoffeescriptだ。
ただし、クラス定義をrequireする際にcoffeescriptファイルを直接参照するのではなく、手順2で作成したファイルを参照する。

具体的には、前回はHogeクラスを参照する際

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

と書いていたが、今回の方法では

{Hoge} = require './test.js'

に変更する。

雑感
しばらくはこの方法で進め、ダメだったら本格的にテストの運用方法を考える。
phamtomjsはnpmから入れられるmocha用のmocha-phantomjsに関する情報が少なかった。
phantomjsが今の所良さげだが、導入例がhtmlファイルにテストを書いてるのが気に入らないので今回は見送った。

参考
PhantomJS + MochaでクライアントサイドJavaScriptのテストをしよう - bokuweb.me - mocha+phantomjs
mochaとphantomJSとtravis-ciでフロントエンドJavaScriptのテスト - Webtech Walker - mocha+phantomjs
node.jsのテスティングフレームワークであるjasmine-nodeをインストールして使ってみる — Toroとトロは電子機械の夢を見るか - jasmine
CoffeeScriptでjasmine-node | ひげろぐ - jasmine+coffeescript
CoffeeScript Cookbook » Testing with Jasmine - jasmine+coffeescript
CoffeeScriptファイルどうやって分けるか問題 - harusamex.blog - coffeescript分割

おまけ
TestWindow.jsはnode.js - Basic error when using jquery with nodejs - Stack Overflowを参考にしたが、そのままでは動かなかった。
不要なvar、セミコロン付け忘れ、windowへの代入タイミングといった修正が必要だった。