PhantomJSとJasmineで振る舞い駆動開発なJavaScriptテスト:フレームワークで実践! JavaScriptテスト入門(2)(3/3 ページ)
しっかりとJavaScriptをテストするために、今注目のJavaScript用のテストフレームワークをいくつか紹介し、その概要から実践的な使い方まで解説する連載
PhantomJSを使ってJasmineのテストを実行する
PhantomJS付属のサンプルを使ってJasmineのテストを実行する
PhantomJSには、さまざまなサンプルスクリプトが付随していますが、その中に「run-jasmine」というスクリプトが存在します。これはその名の通り、指定されたURLにアクセスしてJasmineのテストを実行し、その結果をconsoleに書き出すスクリプトです。
まずは、このスクリプトを試してみたいところですが、PhantomJS 1.7.0付属のrun-jasmine.jsはJasmine 1.2.0用、run-jasmine.coffeeはJasmine 1.1.0用の記述がされており、今回インストールしたJasmine 1.2.0の結果を取得するためには、run-jasmine.jsの方を使用する必要があります。
$ phantomjs ~/phantomjs/examples/run-jasmine.js http://localhost:8080/SpecRunner.html
run-jasmineをカスタマイズする
付属のrun-jasmineは公式ページで「However, these are for illustration purposes, it lacks important reporting features necessary for real-world uses.」(これらのスクリプトは説明用で、実際に使うためには必要な情報が欠けているよ)とあるように、Jasmineの実行結果から特定の部分を抜き出した形になっています。
テストフレームワークの常としてJasmineもテスト結果をどう扱うかはReporter(log4XXX系のAppender相当)に委譲されており、オリジナルのReporterを作って「jasmine.getEnv().addReporter(repoter)」を呼び出すことで、テスト結果の取り扱いを変更できるようになっています。
Reporterの差し替えとなると変更点が大きくなってしまうため、今回の記事ではReporterの差し替えまでは行わず、既存のrun-jasmineスクリプトの修正で以下の2点を改善してみたいと思います。
- テストの実行数が分からない、テストの切れ目が分かりづらいといった表示に関する問題
- expectで失敗した場合、どこで失敗したかのスタックトレースが表示されない問題
テスト結果の見た目を変更
run-jasmine.jsの中身を見てみると、waitFor関数の第1引数に渡している無名関数(56〜59行目)がJasmineテストの終了チェック、第2引数に渡している無名関数(61行目以降)がJasmineの結果を収集している部分になっています。2点の問題のうち、前者に関しては見た目の問題なので、61行目以降を修正すれば出力を変更できそうです。
- run-jasmine-incompete.js(ソースコードがダウンロードできます)
- run-jasmine-incomplete.coffee(ソースコードがダウンロードできます)
今回はRSpecの出力結果に似せて出力を変更してみました。
expectで失敗した場合のスタックトレース表示
見た目は比較的簡単に修正できますが、厄介なのがこちらの問題です。実際のWebブラウザから確認すると、「div.stackTrace」にスタックトレースが格納されているため、単にこれを「console.log」で出力すれば良いように見えますが、先ほどの画像を見ると分かるように、実際にはこれでは一部しかうまくいきません。
例外をthrowしている場合には正常にスタックトレースが表示されていますが、expectに失敗した場合は実際のWebブラウザでは表示されていたスタックトレースが表示されなくなってしまっています。
連載第1回の記事にもありましたが、WebKitエンジンとはいえ、実際のWebブラウザとは異なるところがあり、この問題はその一例といえます。
通常のWebブラウザ、例えばGoogle Chromeで「console.log(new Error().stack)」を実行するとスタックトレースが表示されます。
Error: sample at child (http://example.co.jp/index.html:14:21) at parent (http://example.co.jp/index.html:17:9) at HTMLInputElement.onclick (http://example.co.jp/index.html:23:145)
しかしphantomjs上で同じコードを実行してもundefinedとなってしまいます。Jasmineではexpectに失敗した場合に、同様のコードを実行しているため、実際のブラウザではスタックトレースが取得できるが、PhantomJSでは取得できないという問題が発生してしまいます。
Jasmine側を変更する方法もありますが、今回は「スタックトレースが取れないのはexpectの場合だけで、例外が発生した場合にはPhantomJSでも正常にスタックトレースが取得できる」という点に注目して、run-jasmineの変更を行いました。
変更後のrun-jasmineではexpectに失敗した際に使用されるクラス「jasmine.ExpectationResult」のコンストラクタをフックし、例外の発生とスタックトレースの取得を行うようになっています。
- run-example.js(ソースコードがダウンロードできます)
- run-example.coffee(ソースコードがダウンロードできます)
これに無駄なスタックトレース表示を抑制するなど、いくつかの変更を加えた結果、出力結果は以下のようになりました。RSpecライクでなかなか見やすい形になったのではないでしょうか。
Railsと相性の良いJasmineの拡張も使ってみよう
連載「フレームワークで実践! JavaScriptテスト入門」第2回では、PhantomJSとJasmineを使ったテスト環境を構築するまでをまとめましたが、いかがでしたでしょうか。
今回の記事ではテストの自動実行にまで踏み込んではいませんが、JasmineはRailsプロジェクトと相性が良く、Gem版の「jasmine-gem」、RailsのAsset Pipelineを統合してCoffeeScriptを扱えるようにする「Jasminerice」、ファイルの変更を監視して自動的にJavaScriptテストを実行する「Guard-Jasmine」などが作られています。
またGuard-Jasmineには、JasmineのReporterを差し替えるスクリプトが含まれているため、独自のReporterを作る場合にも参考になるかと思います。
PhantomJSは内部にWebKitブラウザを含んだJavaScript実行環境のため、JavaScript製のテストフレームワークであれば、Jasmineに限らずさまざまなテストフレームワークを動かせます。
次回はPhantomJSはそのままに、Jasmineを「QUnit」に変えた場合の例を見ていきたいと思います。
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- Selenium WebDriverでWebアプリのテストが変わる(前編):iPhone/Android含むブラウザ自動テストの最終兵器Selenium WebDriverとは
Chrome、Firefox、Internet Explorer、Opera、Android、iOSといったブラウザに対応し、Java、C#、Python、Rubyが使えるWebテスト自動化ツールの3つの特徴と環境、実装方法を簡単に紹介 - Webのバグを燃やしまくるFirebugと、そのアドオン7選
- ブラウザを選ばずWebテストを自動化するSelenium
- JavaScriptテストの基礎知識とフレームワーク6選
- Webサイトを“速く”表示させる7つの計測ポイント