Ruby
RSpec
thor

Thor で作ったサブコマンドを Rspec でテストする

More than 1 year has passed since last update.

Ruby はあんま経験がなくてハマったのでメモ。

Thor を使って Git 風の CLI ツールを作ってるんですが、そのテストでコマンドラインオプションとかパラメータを渡す方法がよくわかんなくて、ぐぐって出てくる方法もなんだかうまくいかなくて、テストでハマってどうすんのよ状態だったんですが、本家のリポジトリにやまほどサンプルがあった。

https://github.com/erikhuda/thor

まず spec_helper.rb に以下のようなメソッドを追加。

RSpec.configure do |config|
  ...
  ...

  def capture(stream)
    begin
      stream = stream.to_s
      eval "$#{stream} = StringIO.new"
      yield
      result = eval("$#{stream}").string
    ensure
      eval("$#{stream} = #{stream.upcase}")
    end

    result
  end
end

このメソッドは標準出力をキャプチャして変数に放り込むためのメソッドです。

Thor のリポジトリから丸パクリしました。

https://github.com/erikhuda/thor/blob/master/spec/helper.rb

次にテストコードは以下のような感じ。

require 'spec_helper'
require 'oreore/cli'
require "json"

describe Oreore::Command do

  it "Tests for the oreore cli" do
    output = capture(:stdout) { Oreore::Command.start( %w[record get --app=5] ) }
    expect( JSON.parse( output ).count ).to be > 0
  end

end

この場合、oreore record get --app=5 みたいなコマンドを想定したテストをしています。

$ bundle exec rspec

で合格。すっきりした。

あと、コマンドによっては標準エラーを出して死んでもらうケースもあって、そういう場合は以下のような感じ。

  it "Incorrect parameters" do
    expect{
      capture(:stderr) {
        Oreore::Command.start( [
          "record",
          "get"
        ] )
      }
    }.to raise_error( SystemExit )
  end

expect の後のカッコが丸カッコから波カッコにかわるのか。。。