power-assert

power-assertという単純なアサーションでも、テストが失敗した時に分かりやすい情報を出せるテストライブラリ/ツールについての記事です。

前回、power-assertの使い方 Node.js編 | Web scratchではpower-assertの動作やNode.jsプロジェクトでの簡単な導入方法について解説しました。

前回のpower-assert + gulpで紹介したプロジェクトをそのまま使っていくので、見ていない場合はそちらから見ていたほうがいいかと思います。

今回は、ブラウザでのpower-assertの動かし方とデバッグについて書いていきたいと思います。

今回扱う実行環境

  • Node.js <= 前回
  • ブラウザ
  • Browserify

前回やったこと

まずは前回紹介したgulp + power-assertのプロジェクトを元にやっていきます。

どんな事をやったかを簡単にまとめてみます。

必要なモジュールのインストール

$ npm install --save-dev power-assert gulp gulp-espower
$ npm install -g gulp

テストコードをpower-assert化、mochaでテストを実行するgulpfile.jsのタスクを書きました。

そして、gulp testとするとNode.jsでのテストが動くところまでやりました。

$ gulp test

今回は、これにtestemを使ってブラウザでも同じpower-assertを使ったテストが動くようにしたいと思います。

Testemを使ったブラウザ対応

ブラウザでpower-assertを実行するには、次のようなものが必要です。

  • power-assert化したテストコード(これは既にありますね)
  • test runnerとなるHTMLページ
  • HTMLページで読み込むブラウザ向けのpower-assertの関連ライブラリ
    • Node.jsの場合はrequire("power-assert");で済みますがブラウザは自分で依存関係を解決する必要があります。

素でHTMLページを作り、変換したコード等を読み込んで実行するのでもよいのですが、
その辺はKarmatestem等を使って出来ると思うので、今回はtestemを使ってやってみたいと思います。

そのため、方針としては次のようになります。

  1. ブラウザ向けのpower-assertライブラリをbower install 0.10.2でnpmにもブラウザ向けのファイルが含まれるようになったのでBowerは不要です
  2. testem.json でブラウザでmocha + power-assertで実行出来る環境を作る

完成したサンプルプロジェクトは以下に置いてあります。

追記: 0.10.2からはnpmのみで完結するのでBowerは不要になりました。

次にTestemをインストールしてない場合はインストールしておきましょう

npm install testem -g

Test runnerとなるHTMLページは、testemが内蔵しているため気にする必要はありません。

しかし、<script>タグで必要なアサーションライブラリやpower-asssert等を読み込む必要があります。(require("power-assert");の代わりですね)

その読み込みを、testemの設定ファイルであるtestem.jsonに定義します。

{
    "framework": "mocha",
    "before_tests": "gulp power-assert",
    "on_exit": "rm -rf ./powered-test/",
    "src_files": [
        "./test/*.js"
    ],
    "serve_files": [
        "./node_modules/power-assert/build/power-assert.js",
        "./powered-test/*.js"
    ]
}

設定ファイルの内容を簡単に紹介します。

  • "src_files"は監視対象のファイルです
    • ファイルが変更されたらテストが実行されます
  • "before_tests" はテスト実行前に行う処理です
    • gulp power-assertでpower-assert化しています
  • "on_exit" はtestemが終了した時のクリーンアップ処理です
  • "serve_files" はHTMLページで読み込むファイルです
    • ブラウザで読み込まれるファイルはここに記述します

ブラウザで読み込むべきpower-assertのライブラリ関係はusing grunt-espowerの部分にも書いてあります。

追記 : power-assert 0.7.2から、依存するライブラリをまとめたbuild/power-assert.jsを読み込むだけでよくなりました。

これに加えて、power-assert化したテストファイル("./powered-test/*.js")を読み込みます。

これでブラウザでのテスト準備は完了です。

Testemの実行

設定が面倒くさい分実行は簡単でtestemとすると、ブラウザを受付状態になるので、後はテストしたいブラウザでアクセスするだけです。

$ testem

以下のような感じでテストが出来ます。

Testemの中ではmochaでテストが実行されてるので、基本はあまり変わらないと思います。

power-assert化したコードはsourcemapに対応しているため、
デバッガー等を使ってデバッグも普通に行えます。

ハイブリッドテスト

最初に書いたテストコードではrequireを使ってpower-assertを読み込んでいたので、そのままでは実行時エラーになります。

Node.js環境なら読み込むようにして、ブラウザでは既にglobalで読み込まれているので読み込まないようにすることが出来ます。

if (typeof require == "function" && typeof module == "object") {
    var assert = require("power-assert");
}

これで、Node.js と ブラウザ どちらでも動くテストが書けるようになりました。

先ほどのプロジェクトもNode.jsとブラウザを同時にテスト出来るようにしています。

注記: ブラウザだけがテスト対象なら、上記のrequireそのものを削除しても問題ありません。(というか削除すべき)

また、global.assert = require("power-assert");と定義したものを別のhelperファイルで読み込む等もありでしょう。


Task Runner + Test Runner を使って何とかブラウザでも実行出来るようになりましたが、
上のハイブリッドテストを見て「Nodeで書いたコードをBrowserifyで変換してブラウザで実行すればいいのでは?」と思った方もいると思います。

そういう需要にもpower-assertは対応していて、espowerifyを使うことで出来ます。

espowerifyはその名前の通り、browserifyの変換時にpower-assert化を行えるbrowserifyの変換モジュールです。

browserifyとはNode.jsのコードをブラウザで実行出来るように変換するツールで詳しくは下記を参照して下さい

Browserify

espowerifyはBroserifyの変換モジュールとして扱います。

使い方は単純で browserify -t espowerify のように変換モジュールとして指定するだけで、
browserifyによるnode.jsのコードの変換 + power-assert化を行ってくれます。

この方法のメリットは

  • Node.jsとブラウザで同じテストコードが共有できる
  • 一つのファイルにまとまるため、読み込むファイルの順番などを気にしなくてよい
  • power-asert化も行えるので、他のビルドツール(gulpとか)などは必要としない
  • ソースマップも対応してるのでデバッグできる

デメリットとして、browserifyの変換も入るため変換にかかる時間が増える事があげられます。

先ほどのプロジェクトでやったような依存するライブラリの読み込み等は、
変換して1つになったJavaScriptをtest runnerとなるHTMLページで読み込むだけで良くなるので単純です。

今度はKarmaを使ってブラウザテストしてみましょう。

Karma + Browserify

azu/power-assert-karma-seed

Testemでも出来なくはないですが、karmaにはプリプロセッサという機能があります。
この機能ではプラグインを追加することで、テストを行う前に処理をすることが出来ます。(testemの"before_tests"をより柔軟にできる感じですね)

karma-coffee-preprocessorでcoffeescriptをコンパイルする等色々とプラグインがあります。

そのプリプロセッサで先ほどのbrowserifyによる変換も行う事が出来ます。(これがKarmaを選んだ理由です)

Browserifyを扱う事が出来るプリプロセッサのプラグインとしてkarma-browserifastを使います。

Karmaを使ったプロジェクト設定

まずは必要なものをインストールします(数が多いので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の説明を見ると良いです。

実際のkarma.confの設定はazu/power-assert-karma-seedを参照して下さい

frameworks: ["mocha", "browserify"],
files: [
],
browserify: {
    debug: true,
    files: [
        "test/**/*.js"
    ],
    transform: [
        "espowerify"
    ]
},
preprocessors: {
    "/**/*.browserify": "browserify"
},

本来はfilesでテスト時に読み込むファイルを指定しますが、今回テストしたいファイルはプリプロセッサでbrowserifyしたファイルになります。

そのため、files は空でよくて、代わりにbrowserifyというプロパティのfilesにテストしたいファイルを指定しています。

  • "frameworks""browserify" を入れる
  • browserify の設定をする
    • browserify"transform""espowerify" を指定する
  • preprocessors を設定する(これは常に同じ)

という感じでKarmaの設定は終わりです。

この状態で、karma start + ブラウザでキャプチャ または karma start --browsers Chrome --single-run"という感じでテストを実行すると以下のような事をしてくれます。

  • test/**/*.js 以下のファイルをそれぞれ power-assert化 + browserify化
  • キャプチャしてるブラウザで変換されたテストファイルを読み込んでテストを実行

Karmaのテストサイクルの中で変換、テストの実行をしてくれるので、
見た目的には一時ファイルが必要なくなったり、karma.conf.jsという設定ファイル一つだけ良くなるのがメリットかもしれません。

karma+browserify

こちらもsourcemapに対応してるので、ブレークポイントを貼ったデバッグも可能です。

上記でやってるのは、karma startでサーバを立ち上げて、ブレークポイントを貼って、http://localhost:9876/debug.html に対してChromeでアクセスしてデバッグという感じです。(KarmaのConfigurationをDebug実行だと上手くできない?)

(WebStormでの)Karmaのデバッグ実行は少し特殊な感じなので下記を参照して下さい。


デバッグ

さきほどからsourcemapによるデバッグが可能 ということが書いてありますが、
sourcemapとは何かが気になる人は下記などを見るといいでしょう。

簡単に言うと変換したコード(power-assert化したテストコード)と元のコードの関係をマッピングしたファイルがあることにより、通常のJavaScriptのようにデバッグが可能になる感じです。

現在のブラウザに載ってる開発者ツールやWebStorm等のIDEやエディタでも対応してるものが多いため、デバッグ時にかなり有用になると思います。

こうしたsourcemapの対応が比較的に簡単にできるのもJavaScript ASTをベースとしたツールの特徴でもあるかもしれません。


まとめ

この記事では、以下の事について解説しました。

  • power-assertをブラウザで動かすのに必要なもの
  • Testem + gulp でのブラウザテスト対応
  • Karma + browserifyでのブラウザテスト

power-assertの使い方 Node.js編に比べると、Mocha以外にもtest runnerが必要だったり(両方共内部的にMochaを利用してます)、設定が必要だったりしますが、
power-assert化したテストファイルも問題なくブラウザで動かすことができました。

また、sourcemapにも対応しているのでデバッグも問題なくできることがわかりました。

どんなテストライブラリ(アサーション)を使うか迷ってる人は、一度 power-assert を試してみるのも楽しいと思います。

より良きJavaScriptテストを!