mocha + power-assertを導入してみた(ブラウザもnode.jsも)
テスト書いてないとかお前それ @t_wada の前でも同じこと言えんの?
こんにちは。皆さんテストは書いていますか。
私はAngularJSを書き始めた当初Jasmineを使い、以後1年以上そのままだったのですが、周りの流れがどうもmochaらしいのと、t_wada氏のpower-assertを試してみたかったことから、今回一念発起して乗り換えました。今回はその内容のメモです。
あと、grunt
です。(gulp
は全然勉強してない)
変更前の環境
クライアント・サイド (Browser)
grunt
jasmine
karma
karma-jasmine
サーバ・サイド (node.js)
grunt
jasmine-node
両サイドともフレームワークにjasmine
を用いて、テストランナーにはjasmine-node
やkarma
を使用、grunt
で監視して動かすといった構成でした。
クライアントではAngularJSを書いているため、jasmine
標準のspyやmockを多用しています。
サーバ・サイドのmocha + power-assert導入
クライアントとサーバでは導入法が異なります。まずはnode.js向けの話です。
package.json
{
"devDependencies": {
"grunt": "~0.4.5",
"grunt-espower": "~0.9.1",
"grunt-este-watch": "~0.1.18",
"grunt-mocha-istanbul": "~2.2.0",
"load-grunt-tasks": "~1.0.0",
"power-assert": "~0.9.1"
}
}
今回の内容に無縁なものは除外して載せています。npm
やgrunt
の使い方などはここでは割愛します。
-
#
grunt-espower
-
power-assert
を利用するためには一度コードを変換する必要がある。
-
-
#
grunt-este-watch
- 監視のためのもの。
grunt-contrib-watch
より使い勝手がよかった。今回の話とは関係ない。
- 監視のためのもの。
-
#
grunt-mocha-istanbul
-
mocha
が含まれている。istanbul
はカバレッジの可視化ツールなのでこの際こっちにしてみた。
-
-
#
load-grunt-tasks
-
grunt.loadNpmTasks()
を省略できる。今回の話とは関係ない。
-
-
#
power-assert
- 一番重要なアサーション・ツール。
Gruntfile.js
grunt.initConfig({
dir: {
espowered: 'espowered/'
},
src: {
spec: '**/*-spec.js'
},
espower: {
test: {
files: [
{
expand: true,
cwd: 'test/',
src: ['<%= src.spec %>'],
dest: '<%= dir.espowered %>',
ext: '.js'
}
]
}
},
mocha_istanbul: {
test: {
src: '<%= dir.espowered %>',
options: {
mask: '<%= src.spec %>',
reportFormats: ['lcov']
}
}
},
// ...
この辺は各々のREADMEを参照してください。mocha_istanbul
はこの設定だけで動いたので優秀です。
[
'ts',
'espower',
'mocha_istanbul',
// ...
]
タスクはこんな感じ。ts
はTypeScriptのコンパイルです。
specを修正
mocha
はjasmine
と同じようにdescribe, itの記法なので大幅に書きなおす必要がありません。
冒頭にvar assert = require('power-assert');
を追記して、jasmine
のアサーションをpower-assert
に書き換えていくだけです。
あとはgrunt
を実行すれば、espower
で変換→mocha
で実行→istanbul
のカバレッジ保存、という流れになっています。
クライアント・サイドのmocha + power-assert導入
続いてクライアント・サイドです。こちらの手順は色々みているとBrowserify
を使ったりなんやかんや…、と拒絶反応を起こしそうだったので、学習コストを低くする今に近い構成としました。
概要としては、
karma
karma-mocha
PhantomJS
といった感じです。karma
はAngularJSチームが開発したテストランナーです。
package.json
{
"devDependencies": {
"grunt": "~0.4.5",
"grunt-espower": "~0.9.1",
"grunt-este-watch": "~0.1.18",
"grunt-karma": "~0.9.0",
"karma": "~0.12.24",
"karma-coverage": "~0.2.6",
"karma-mocha": "~0.1.9",
"karma-mocha-reporter": "~0.3.1",
"karma-phantomjs-launcher": "~0.1.4",
"load-grunt-tasks": "~1.0.0"
}
}
-
#
grunt-karma
-
grunt
からkarma
を動かすためのもの。
-
-
#
karma
- テストランナー本体。
-
#
karma-coverage
-
istanbul
を用いたカバレッジ可視化をkarma
がやってくれる。karma-runnerのプロジェクト下で開発されているのも強み。
-
-
#
karma-mocha
-
karma
でmocha
を使うためのもの。他にもjasmine
用のプラグインなど複数ある。
-
-
#
karma-mocha-reporter
- 後述。
-
#
karma-phantomjs-launcher
-
karma
の扱うブラウザをPhantomJSにするためのもの。これでTerminal内でクライアント・サイドのテストが完結する。(※)
-
power-assert
はここには記述しません。
※注意: karma-phantomjs-launcher
が利用するPhantomJSの現時点でのバージョンではFunction.prototype.bind
が実装されていないようで、この処理を利用したい場合は# es5-shim
を利用すると良いです。
bower.json
{
"dependencies": {
"power-assert": "*"
}
}
power-assert
はbower側に記述します。
Gruntfile.js
espower
の設定はサーバ・サイドのときと同様です。ここにkarma
の設定が加わります。
// ...
karma: {
unit: {
configFile: 'karma.conf.js',
singleRun: true
}
},
// ...
といってもGruntfile.js
に書くのはこれだけで、詳細はkarma.conf.js
に記述します。
[
'ts',
'espower',
'karma',
// ...
];
タスクは、espower
で変換してからkarma
の順です。
karma.conf.js
// Karma configuration
// http://karma-runner.github.io/0.10/config/configuration-file.html
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['mocha'], // 重要!
files: [
'app/bower_components/angular/angular.js', // こんな感じで
'app/bower_components/jquery/dist/jquery.js', // ブラウザで使うライブラリを指定
'app/bower_components/power-assert/build/power-assert.js', // 重要!
//
'lib/**/*.js', // 元となるソース
'espowered/**/*.js' // spec, ただし espowered/ の方を指定する
],
exclude: [],
port: 8080,
logLevel: config.LOG_INFO,
autoWatch: false,
// カバレッジの取得元を記述
preprocessors: {
'lib/**/*.js': 'coverage'
},
// mocha とは karma-mocha-reporter のこと
// coverage を集計するなら 'coverage' も追加
reporters: ['mocha', 'coverage'],
colors: true,
browsers: ['PhantomJS'],
singleRun: false
});
};
最初karma-mocha-reporter
無しのまま動作させてみたんですが、karma
が生成する結果ログを表示するだけで、せっかくのmochaらしい表示がされず不満だったので、karma-mocha-reporter
というプラグインを導入しました。これでmochaらしいリスト表示やチェックマークなどがkarmaログに続いて表示されます。
今後の課題
mocha
にはspyやmockといった仕組みが無く、別のライブラリを組み合わせるらしいので、AngularJSのテストはまだまだjasmine
と併用になるかという感じです。
私の下では巨大な本体と分割したプロジェクトを動かしているので、小規模なものから順次mocha
にして、大規模な本体側は当面jasmine
のまま移行を続けるという予定で考えています。protractor
#との併用も悩ましいですが、今回は省略しました。
まとめ
jasmine
を使っていても簡単に乗り換えられることが分かりましたね! mocha
にしたけどspecを全部書き換えるのは大変…というときはexpectations
#というjasmine APIと共通のインタフェースを持つライブラリがあるようなので安心です!(@vvakame氏ありがとう)
それでは、mochaのナイスなログ表示と強力なpower-assertで快適なテストライフを!
Discussion