Hubot スクリプトを gulp と mocha でテスト駆動開発する
今まで 3つの Hubot スクリプトを作って、npm で公開していますが、ユニットテストがないのが、気持ち悪かった & 非効率だったので、gulp と mocha を使って、ユニットテストを追加しました。
package.json
devDependencies に以下のパッケージを追加しました。
テスト用のモジュールを読み込む
以下のモジュールを採用しました。
expectマッチャーを使うための [Chai Assertion Library]。- 偽装 HTTP レスポンスを行うための nock。
yourscript_spec.coffee の先頭に以下のコードを追加します。
偽装 Hubot アダプタ
hubot-mock-adapter は send, reply, topic, play イベントを即時に実行する、シンプルな Hubot アダプタです。
mock-adapter を使って Robot インスタンスを作成します。
これは、以下の意味があります。
- npm モジュールからアダプタを読み込む。
- hubot-mock-adapter を採用する。
- HTTP サーバーは有効。
TestHubot ...が先頭に付いているメッセージに反応する。
自分のスクリプトを読み込む
Robot:loadFile メソッドを実行して、テストを行いたいスクリプトを読み込みます。
This method loads listeners and parses command.
このメソッドは、リスナと、コメントに記載されているコマンド例をパースします。
アダプタがデータソースに接続されている必要があるので、connected イベントハンドラ内で実行します。
hubot help コマンドは help.coffee で実装されいます。
help コマンドをテストする
Robot:loadFile メソッドは、非同期でスクリプトを読み込み、コマンド例をパースします。
なので、実際にそのコマンドが読み込まれたか確認してから、scope を抜ける必要があります。
それで help コマンドの応答をテストすることができます。
Hubot v2.7.5 は、ヘルプのパース処理に、接頭辞を2度付与するバグがあります。
修正して、pull request#712 を送り、マージされました。(まだ npm では公開されていません。)
イベントハンドラで例外を受け取る
イベントハンドラ内でテストに失敗すると、chai.AssertionError が投げられ、そのままだと、プロセスを終了してしまいます。
try catch で囲んで、もし例外を受け取った場合は、done メソッドの引数に、エラーオブジェクトを渡します。
偽装 HTTP
偽装 HTTP レスポンスを行うために、nock を採用しました。nock は、ネイティブ実装の http.ClientRequest モジュールのレスポンスを上書きします。
nock は、全ての HTTP 通信をブロックする機能があるので、beforeEach で nock.disableNetConnect() を実行して、有効にします。
詳しくは nock のドキュメントを参照してください。
afterEach でお掃除するもの
HTTP サーバーを閉じる
express サーバーを閉じないと、次のテストで Error: listen EADDRINUSE (ポートがほかで使われている) が発生して、クラッシュしてしまいます。
偽装 HTTP を掃除
もし、エラーハンドリングのテストを前に行っていた場合、次のテストで同じエラーが発生してしまうので、nock.cleanAll() を実行して、偽装 HTTP を掃除します。
gulpfile.coffee
バージョン 3.7.0 から gulp は CoffeeScript で書かれた gulpfile をサポートしています。
gulp watch がテストに失敗すると終了する
gulp-watch は何もしないと、テスト失敗時に終了してしまいます。
以下の様に、エラーハンドラ内で end イベントを発生させ、これを回避します。
mocha パイプは coffee パイプにつながっていることを確認してください。
関連記事
2014-06-09
2014-05-24