Hubot スクリプトを gulp と mocha でテスト駆動開発する

·1 分で読めます

今まで 3つの Hubot スクリプトを作って、npm で公開していますが、ユニットテストがないのが、気持ち悪かった & 非効率だったので、gulpmocha を使って、ユニットテストを追加しました。

package.json

devDependencies に以下のパッケージを追加しました。

テスト用のモジュールを読み込む

以下のモジュールを採用しました。

  • expect マッチャーを使うための [Chai Assertion Library]
  • 偽装 HTTP レスポンスを行うための nock

yourscript_spec.coffee の先頭に以下のコードを追加します。

偽装 Hubot アダプタ

hubot-mock-adaptersend, 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 通信をブロックする機能があるので、beforeEachnock.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 パイプにつながっていることを確認してください。