QunitによるWeb標準系UIのシナリオテスト
このエントリーはHTML5 Advent Calendarに参加しています。本当は18日目だったのですが、こんな時間になってしまいました。
Web標準系UI、というのは私が勝手に呼んでいる呼称なのですが、HTML+JavaScript+CSSを使ったUIのことです。なので、大まかにはWebサイトなども含まれます。
Web標準系UIは表現力の高さが魅力ですが、その分、画面が正常に動作するかのテストが大変です。もちろんSeleniumというツールもあるのですがこれは有名なので適当に検索してもらうとして、今回はあまりこういった文脈では紹介されることないQunitを紹介したいと思います。
QUnitとは?
元々はjQueryのテスティングフレームワークとして開発されたもので、その時はJQUnitという名前でした。現在はjQueryから独立して依存性をなくしています。
各言語にある同様のツールとひとまとめにしてxUnitという呼称でグルーピングされている単体テスト向けフレームワークなのですが、基本となっている言語がjavascriptなので、一般的なサーバーサイドの出力として使われるJSON、HTML、XMLといった出力の分析に使えるという特徴があります。このため、画面出力から切り離してサーバーサイドの出力をテストしたい場合にも有効に使えます。
インストールと実際のテスト
QUnitのインストールはとても簡単です。レポジトリからダウンロードしてきて適当な場所に配置するだけです。test以下にあるHTMLファイルを編集することで、テストの記述ができます。
単体テストのやり方自体は、このエントリーが詳しいので参考にしてください。
このテストの際に通信部分にjQueryを使うと、サーバーサイドの出力をパースしてその結果を元にテストできます(jQueryでxmlをパースする例)。
HTMLファイルの場合、IDやセマンティックなタグを生かしたコード規約を決めておくと将来的な変更に対しての追加コストが少なくなるでしょう。
シナリオテストをする
ざっくりとして記述でしたが、これでそれなりの説明になっていることからわかりますように単体の機能へのテストに対してはQUnitはシンプルで強力な機能を提供してくれます。しかし、前提となる操作を必要とする操作をテストするためのシナリオテストの場合、QUnitには落とし穴があります。
QUnitは各テストをそれぞれ独立したテストとして実行します。なので、一時的にテストを停止するためのstopや非同期処理のためのテストであるasyncTestを使ったとしても、別のテストはそのまま実行されてしまいます。
asyncTest("asyncTestBad1",function(){ jQuery.get("/test/example/",function(data){ start(); same(data.test, "ok"); }); }); asyncTest("asyncTestBad2",function(){//このテストが前のテストの終了を待たずに実行される jQuery.get("/test/example/next",function(data){ start(); // 10ms後再会 same(data.test2, "ok"); }); });
このため、非同期処理である通信を伴うテストの場合、一種のコールバック関数群としてテストを記述する必要があります。
asyncTest("asyncTestOK1",function(){ jQuery.get("/test/example/",function(data){ start(); same(data.test, "ok"); test2(); }); }); function test2(){ asyncTest("asyncTestOK1",function(){ jQuery.get("/test/example/next",function(data){ start(); same(data.test, "ok"); //必要ならば次のテストを呼び出す関数をここに書く }); }); }