読者です 読者をやめる 読者になる 読者になる

その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

PhantomJS + QUnit (with qunit-tap.js) + prove を使ってJavaScript のテストをTAP で回す

javascript test

QUnit とTAP を用いた JavaScript のテスト環境構築の話です。

前提として、QUnit でテストを実行出来る環境が構築できていることとします。
QUnit の実行のやり方等は以下のエントリが詳しくてマジ最高なので、ご参照下さい。
QUnitの基本的な使い方 - Block Rockin’ Codes

さて、今回例として扱うディレクトリの構成としてはこんな感じです。

.
├── lib
│    ├── qunit.css
│    └── qunit.js
├── main.js
├── test.html
└── test.js
  • main.js: テストの対象となる JavaScript ファイル
  • test.html: テストの結果を表示するための html ファイル
  • test.js: JavaScript のテストコード
  • lib以下: QUnit 本体

この段階でtest.html をウェッブブラウザで開くとテストが走り、結果を閲覧出来るはずです。

沸き立ち上がる要求

  • ウェッブブラウザで test.html を開かないとテスト結果を確認できなくてちょっとだるい
    • さらに言うと目視で確認しなければならないのでちょっとだるい
  • 俺は CLI でやっつけたいんだ!!!!!
    • そうすれば終了ステータスで成功したか失敗したかも分かるし便利
  • そしてそれを CI で回したい

PhantomJS + QUnit (with qunit-tap.js) + prove

今回は、上記の要求をこの構成で実現しました。

手順1. PhantomJS のインストール

まず、PhantomJS をインストールします。
ご存知の事とは思いますが、PhantomJS は WebKit ベースのヘッドレスブラウザ (つまりGUI の無いブラウザ) です。
もの凄く雑な (本当に雑な) 説明をすると、コマンドライン上で動くブラウザという感じでしょうか。

PhantomJS はソースコードから make してインストールしようとすると (まじでマジで真剣で) ダルい上に、
コンピュータが暖房機器と化してしまうのでオススメ出来ません。この時期は特に!
なので、特別な理由が無い限りは各プラットフォームに対応したバイナリをインストールするのが良いと思います。
(Debian 系だと apt-get あるいは aptitude、RHEL 系だと yum、Mac OS X だと brew でインストールすると良いでしょう)

インストールの方法は以下が詳しいのでご参照ください
http://phantomjs.org/build.html

手順2. run-qunit.js をダウンロード

run-qunit.js をダウンロードして配置します。

run-qunit.js
https://raw.github.com/ariya/phantomjs/master/examples/run-qunit.js
(「名前をつけて保存」とか、wget とか curl とかでダウンロードすると良いと思います)

run-qunit.js は PhantomJS で QUnit を動作させるためのスクリプトです。
任意の場所に配置して良いですが、プロジェクトディレクトリ以下に配置すると便利かもしれません。
今回の例では vendor/ というディレクトリを掘ってそこに配置する事とします。

実はこの時点で、PhantomJS によるテストは可能となっています。
$ phantomjs vendor/run-qunit.js test.html
とタイプして実行してやるとテストが走ります。走りましたね?
ただ、このままだとちょっと見づらいので、以降の手順で視認性を上げます*1

手順3. qunit-tap.js をダウンロード

qunit-tap.js をダウンロードして配置します。

qunit-tap.js
https://raw.github.com/twada/qunit-tap/master/lib/qunit-tap.js

qunit-tap.js は t_wada さんが開発した、QUnit の出力を TAP 形式にするためのプラグインです。

TAP については以下が詳しいので、興味のある方はご参照ください。
TAP(Test Anything Protocol) : ash
第1回 Perlにおけるテストの概要/TAPとは?:Happy Testing Perl|gihyo.jp … 技術評論社
404 Blog Not Found:「同じコード」の同じって何さ - TAPのススメ

なお、こちらの qunit-tap.js も任意の場所に配置して大丈夫です。
こちらのファイルも、今回は vendor/ 以下に配置する事にします。

現時点での tree は以下のようになっています。
.
├── lib
│    ├── qunit.css
│    └── qunit.js
├── main.js
├── test.html
├── test.js
└── vendor
      ├── qunit-tap.js
      └── run-qunit.js

手順4. test.html を書き換える

文章で説明するのもアレなんで、 コードで説明します。

test.html は初期状態だとこんな感じになっていると思います (QUnit の test/index.html より拝借)。
https://gist.github.com/moznion/6001797/8084086c6eb33bc28e7d4cf3de03b9de3389c9cb

これに c68243e のコミットの変更 (つまり最新のコミットの内容) を書き加えます。
https://gist.github.com/moznion/6001797/revisions
(qunit-tap.js のパスについては、環境に合わせて適宜書き換えて下さい)
(ファイル末尾の の変更に関しては無視して下さい)

この時点で、PhantomJS 上かつ TAP 形式でテストを実行することができます。
先ほどと同様に、
$ phantomjs vendor/run-qunit.js test.html
と実行してやると、TAP 形式で結果が出力されるはずです。

手順5. Test::Harness (prove) の更新

古い Test::Harness (prove) を使うと悲劇が起こるかもしれないので、このモジュールを更新します。
$ cpanm Test::Harness
とか
$ cpan Test::Harness
と実行してやればOKです。

手順6. prove でテストを実行する

$ phantomjs vendor/run-qunit.js test.html
↑のコマンドではなく、prove でテストを実行すると色々と良い事があります。

良い事っていうのは主に “state” オプションのことで、この state を使いこなすと、
「前回失敗したテストのみを実行する」だとか、「変更があったものだけを実行する」といったインテリジェントな処理が可能になります。
使い方はまだまだたくさんあるので、詳しくは以下をご覧ください。
prove についてのおさらい - Perl Advent Calendar Japan 2011 Test Track

prove でテストを実行するときには
$ prove --exec="phantomjs vendor/run-qunit.js" test.html
とすると走るはずです。走りましたでしょうか?



これで CLI から JavaScript のテストを実行できる上に、CI でもガンガン JS のテストを回せますね!!!!!
ハピネス!!!!!!!

*1:まあ、視認性だけが目的ではありませんが……