hubotコマンドのregexだけをテストしたいんだよね
hubot でも E2E テストをしようぜって話をしてる人がいてすげーなって思ってたんですけど、hubot: pingって叩くと PONG って書いてくるとかなら(つまりは非破壊的な動作なら)、テストしやすいなーって思ってたんですけど、例えば deploy のコマンドの返事だけを regex でテストするってのはどうもイケてるとは思いませんでした。そこで、前回、hubot でも MVWhatever しようってことで、models とかに実際呼び出されるメソッドを切り出すって話をしたので、hubot のコマンド自体にテストをしたいなーって話です。
hubot コマンドの regex 正しく吸われているかどうかのテスト
まずは mocha と chai を入れときましょう(まぁ、jasmine でも ava でもなんでもいいです)。
npm install mocha chai --save-dev
それと、どっかにつなぎにいってもいやなので、mock-adapter も入れときましょう。
npm install hubot-mock-adapter
っでは実際に regex のテストを書いてみます。まずは本体から。
# scripts/deploy.coffee
# Description
#   Deploy
#
# Commands:
#   hubot: deploy to ENVIRONMENT:REVISION
# ダミーのコントローラー
Controller = require './controllers/deploy_controller'
module.exports = (robot) ->
  robot.respond /deploy\s+([\w._-]+)\s*:\s*([\w._-]+)\s*$/, (res) ->
    environment = res.match[1]
    revision = res.match[2]
    controller = new Controller environment, revision
    controller.execute()
んでこれをテストしたい。
# test/regex/deploy.coffee
{expect} = require 'chai'
{Robot} = require 'hubot'
describe 'deploy', ->
  environment = 'production'
  revision = 'v0.1.0'
  robot = new Robot null, 'mock-adapter', false, 'test-hubot'
  # regexのテストしかしない(状態遷移についてのテストがない)ので、afterやbeforeEachのようなフックは使用しない
  regex = require('../../scripts/deploy')(robot).listeners[0].regex
  # まずは環境名とリビジョンが正しく取れるかどうかのテスト
  context 'with input = "test-hubot: deploy production:v0.1.0"', ->
    it 'gets environment and revision', ->
      match = regex.exec "test-hubot: deploy #{environment}:#{revision}"
      expect match[1]
        .to.be.equal environment
      expect match[2]
        .to.be.equal revision
  # regexにマッチしないことを確認するテスト
  context 'with input = "test-hubot: deploy production:********"', ->
    it 'does not match', ->
      match = regex.exec "test-hubot: deploy #{environment}:********"
      expect match
        .to.be.equal null
みたいな。これできれいにコマンドの regex 部分を切り分けることができましたね。コマンドが長くなってくると TYPO も結構怖かったり、コマンド数が増えてくると予期せぬ match が発生(え、このコマンドこっちにも match しちゃうのかーみたいな)するので、regex をテストしておくってのはお手軽な割に以外に大事だなーって思ってます。
あとは npm test できるように package.json に
..snip..
  "scripts": {
    "test": "mocha --compilers coffee:coffee-script/register --recursive test/"
  }
..snip..
とかやっとけばいい感じだと思います。