Power Assertとはassert(a === b);
のような単純なアサーションでも、
Assert失敗時(テストが通らなかった時)に分かりやすい情報を表示できるようにする機能の事を言います。
JasmineやChaiが持つshould
やexpect
等言った豊富なアサーションを覚える必要なく、
シンプルにassertを使うだけでも十分な失敗時の情報が得られるため、沢山のアサーションを使い分けしなくていいというメリットがあります。
実際に書くことはrequire('power-assert');
以外は殆どassert
モジュールを使った場合と同じ事がわかります。
var assert = require('power-assert');describe('Array', function(){ beforeEach(function(){ this.ary = [1,2,3]; }); describe('#indexOf()', function(){ it('should return index when the value is present', function(){ var zero = 0, two = 2; assert(this.ary.indexOf(zero) === two); }); }); });
この記事ではPower AssertのJavaScript実装であるtwada/power-assertの使い方について紹介します。
power-assert の役割について簡単に解説します。
power-assertはchai等のようなアサーションのライブラリというわけではなく、コードの変換や失敗時の出力等がまとまったツールに近い位置のものです。
簡単に流れを見ると以下のような事をします。 (この流れは自動化できるので単純に実行時に全部やってるわけじゃないということがわかればいいと思います)
- テストコードをpower-assert用に変換したコードを生成します
- power-assert化されたテストコードを実行します
- テストが失敗してる時は、ロードしてる
power-assert
モジュールが整形してエラー情報を出力します
1 でテストコードを変換する事で、3でテストが失敗した時に詳細な情報が出力出来るように書き換えたテストコードを作成しています。
2 で実行する際に使われる assert()
といったアサーションは、Node.jsのAssert等をそのまま使うようになっています。
詳しくは下記を見るといいと思います
本題のpower-assertの使い方について実行環境別に紹介します。
- Node.jsh
- ブラウザ
- ハイブリッド(ブラウザ/Node.js)
- Browserify
それぞれ実行するまでの設定をしていくので、必要な部分だけ見ていくといいでしょう。
twada/power-assert - HOW TO USE にも使い方が書いてあるためそちらも参照して下さい。
使い方の前にで紹介したように、power-assertは変換と実行の2つフェーズがあります。
変換のフェーズはgulp-espower、grunt-espowerというタスクが用意されているので、これを使うのが簡単でしょう。
power-assertはアサーション周りについてのみ扱うので、describe()
や Qunitのtest()
といった部分に何を使うかというのは特に制限はありません。
基本的にはMochaで実行するのが一番相性がよいため、Test RunnerはMochaを使っていきます。
Mocha + Grunt は下記にかかれているので、 Mocha + Gulpでやってみたいと思います。
サンプルプロジェクトは以下に置いてあります。
まずは、必要なモジュールをインストールします
npm install --save-dev power-assert gulp gulp-espower testem
次にgulpの設定ファイルであるgulpfile.jsを書きます。
gulpのtaskでは次の2つを定義しています。
- power-assert化されたテストコードに変換する
"power-assert"
タスク - 変換されたテストコードをmochaで実行する
"test"
タスク
2の "test"
タスクを行う前に、自動的に変換しておいて欲しいのでgulp.task
の依存関係も定義しておくと、
gulpfile.jsは以下のように書けると思います。
"use strict"; var gulp = require("gulp"); var espower = require("gulp-espower"); var mocha = require("gulp-mocha"); var paths = { test: "./test/*.js", powered_test: "./powered-test/*.js", powered_test_dist: "./powered-test/" }; gulp.task("power-assert", function () { return gulp.src(paths.test) .pipe(espower()) .pipe(gulp.dest(paths.powered_test_dist)); }); gulp.task("test", ["power-assert"], function () { gulp.src(paths.powered_test) .pipe(mocha()); });
これでnodeで実行出来る環境が出来ました。
test/
以下にテストを書いていって、テストを実行したい時は以下のようにコマンドを叩くと実行結果が出力されるようになります。
gulp test
次は、これをブラウザでも実行出来るようにしたいと思います。
ブラウザで実行するには、power-assert化したテストコード(これは既にありますね)と、ブラウザ向けのpower-asser
のアサーションライブラリ、test runnerとなるhtmlページ
が必要となります。
素でHTMLページを作って変換したコード等を読み込んで実行するのでもいいですが、 その辺はKarmaやtestem等を使って出来ると思うので、今回はtestemを使ってやってみたいと思います。
方針としては次のようになります。
- ブラウザ向け
power-asser
ライブラリをbower install testem.json
でブラウザでmocha + power-assertで実行出来る環境を作る
ブラウザ向けpower-asser
はBowerを使うことで簡単にインストールできます。
bower init
bower install power-assert --save
で1のインストールが完了です。
Test runnerとなるhtmlページは、testemが内蔵しているため気にする必要はありませんが、
ブラウザで実行するために<script>
タグで必要なアサーションライブラリやpower-asssert
等を読み込む必要があります。
その読み込みを、testemの設定ファイルであるtestem.json
に定義します。
{
"framework": "mocha",
"src_files": [
"./bower_components/assert/assert.js",
"./bower_components/empower/lib/empower.js",
"./bower_components/power-assert-formatter/lib/power-assert-formatter.js",
"./bower_components/power-assert/lib/power-assert.js",
"./powered-test/*.js"
]
}
ブラウザで読み込むべきJavaScriptファイルはusing grunt-espowerの部分にも書いてありますが、 Bowerでインストールしたpower-assertの関連ファイルを読み込み、その後にpower-assert化したテストファイルを読み込む用に定義しています。
これでブラウザでpower-assert化したテストを実行準備は完了です。
実行の前に、テストを書き換えた時にpower-assert化の変換をgulp power-assert
で行うのは面倒なので、gulpfileにテストファイルの変更を監視して変換を行うgulp watch-power-assert
を追加しました。
実行する時は、以下のようになります
gulp watch-power-assert # 1. テストファイルのpower-assert化
testem # 実行したいブラウザで開く
やっている流れとしては以下のような事をやっています(遠いですね…)
testem と gulp watchを起動 -> テストコードのpower-assert化変換 -> testemが変換コードの更新検知 -> testemがテストを実行する
最初に書いたテストコードではrequire
を使ってpower-assertを読み込んでいたので、そのままでは実行時エラーになります。
Node.js環境なら読み込むようにして、ブラウザでは既にglobalで読み込まれているので読み込まないようにすることが出来ます。
if (typeof require == "function" && typeof module == "object") {
var assert = require('power-assert');
}
これで、Node.js と ブラウザ どちらでも動くテストが書けるようになりました。
Task Runner + Test Runner を使って何とかブラウザでも実行出来るようになりましたが、 上のハイブリッドテストを見て「Nodeで書いたコードをブラウザで実行すればいいのでは」と思った方にはespowerifyを使うことでもっと楽に出来ます。
espowerifyはその名前の通り、browserifyの変換時にpower-assert化を行うモジュールです。
browserifyとはNode.jsのコードをブラウザで実行出来るように変換するツールで詳しくは下記を参照して下さい
espowerifyはBroserifyの変換モジュールとして扱います。
使い方は単純で browserify -t espowerify
のように変換モジュールとして指定するだけで、
browserifyによるnode.jsのコードの変換 + power-assert化を行ってくれます。
この方法のメリットは
- Node.jsとブラウザで同じテストコードが共有できる
- 一つのファイルにまとまるため、読み込むファイルの順番などをきにしくなくていい
- power-asert化も行えるので、他のビルドツールなどは必要としない
- 2014年4月2日現在ではソースマップが対応されてるのでデバッガーが使いやすい
デメリットとして、browserifyの変換も入るため変換にかかる時間が増える事があげられます。
後は、変換してまとまったJavaScriptをtest runnerとなるhtmlページで読みこめばテストが出来ますが、今回はKarmaを使ってテストしてみましょう。
karmaにはプリプロセッサという機能があり、 この機能ではプラグインでcoffeescriptのコンパイルなどの処理を行う事が出来ます。
そのプリプロセッサで先ほどのbrowserifyによる変換を行う事が出来ます。
browserifyを扱う事が出来るプリプロセッサとしてkarma-browserifastを使います。
まずは必要なものをインストールします(数が多いのでpackage.jsonを見るといいです)
npm install -g karma-cli
npm install --save-dev espowerify karma karma-browserifast browserify mocha
必要なモジュールをインストールしたら、Karmaのセットアップを行います。
詳しいKarmaの使い方はKarma - Configuration等を見ましょう
karma init # mochaを選択する
次に、browserifyの設定を行います。
詳しくはkarma-browserifastの説明を見ると良いのですが、本来はfiles
でテスト時に読み込むファイルを指定しますが、今回テストしたいファイルはプリプロセッサでbrowserifyしたファイルになります。
そのため、files
は空でよくて代わりにbrowserify
というプロパティにテストしたいファイルを指定しています。
frameworks
にbrowserify
を入れるbrowserify
の設定をするbrowserify
のtransform
に"espowerify"
を指定するpreprocessors
を設定する(これは常に同じ)
frameworks: ['mocha', "browserify"],
files: [
],
browserify: {
debug: true,
files: [
"test/**/*.js"
],
transform: [
"espowerify"
]
},
preprocessors: {
"/**/*.browserify": "browserify"
},
という感じでKarmaの設定は終わりです。
この状態で、karma start
+ ブラウザでキャプチャ または karma start --browsers Chrome --single-run"
という感じでテストを実行すると以下のような事をしてくれます。
test/**/*.js
以下のファイルをそれぞれ power-assert化 + browserify化- キャプチャしてるブラウザで変換されたテストファイルを読み込んでテストを実行
Karmaのテストサイクルの中で変換、テストの実行をしてくれるので、 見た目的には一時ファイルが必要なくなったり、karma.conf.jsという設定ファイル一つだけ良くなるのがメリットかもしれません。
SourceMapがあるためブレークポイントを貼ったりデバッグがしやすいです。 (他の方法でもpower-assert化するときにsourcemapを作成すれば対応できそう)
power-assert はNode.js環境で動かすのが一番簡単です。
Mochaには--require
というテスト実行にnode moduleを読み込む仕組みがあります。
この読み込むモジュールにespower-loaderを使う事で簡単にpower assertを導入できます。
espower-loaderの説明を読むと、enable-power-assert.js
設定ファイルが必要になりますが、毎回書くことは同じなので、intelli-espower-loaderを使うと余計な設定ファイルなしに利用できます。
intelli-espower-loader では設定をnpmのpackage.json
に持たせることで設定ファイルをなくしています。
そもそも何を設定する必要があるかというと、テストファイルがどこにあるかという事を指定する必要があります。
power-assertを使いたいプロジェクトにintelli-espower-loaderをインストールします。
npm install power-assert intelli-espower-loader --save-dev
package.jsonに"directories"
という項目を追加して、"test"
の値にテストディレクトリを指定します。(そのディレクトリ以下にあるファイルがpower assert化の対象になります)
"directories": {
"test": "test/"
}
後は、mochaで実行するときに--require
でintelli-espower-loaderを指定するだけです。
mocha --require intelli-espower-loader