[RSpec 3] STDOUT の output を RSpec 3 でテストする
先日、Test::Unit で STDOUT の出力をテストするコードに手間取った。
#output.to_stdout
RSpec 3 であれば、シンプルにテストできそうなので試す。
コンソールに下記を出力するメソッドを用意する。
1
2
Fizz
4
Buzz
FizzBuzz
こんな形。
class FizzBuzz
def foo
puts "1\n2\nFizz\n4\nBuzz\nFizzBuzz\n"
end
end
これをテストするコード。
output(***).to_stdout
だけで良い。
require_relative '../fizzbuzz'
describe FizzBuzz do
before do
@fizz_buzz = FizzBuzz.new
end
describe '#foo' do
let(:out) { "1\n2\nFizz\n4\nBuzz\nFizzBuzz\n" }
it '' do
expect { @fizz_buzz.foo }.to output(out).to_stdout
end
end
end
Test::Unit を書き換え
なので Test::Unit でこんな形で書いていたものが
require 'test/unit'
require 'stringio'
require './fizzbuzz'
class TestFizzBuzz < Test::Unit::TestCase
def setup
ARGV[0] = 15
@fizz_buzz = FizzBuzz.new
@ans = [1, 2, 'Fizz', 4, 'Buzz', 'Fizz', 7, 8, 'Fizz', 'Buzz', 11, 'Fizz', 13, 14, 'FizzBuzz']
end
def test_console
$stdout = op = StringIO.new('', 'w')
result = ->(max) { @fizz_buzz.map_upto(max, @fizz_buzz.method(:fizzbuzz)) }
@fizz_buzz.console(result)
out = str2fizzbuzz_list(op.string)
assert_equal(@ans, out)
ensure
$stdout = STDOUT
end
def str2fizzbuzz_list(str)
str.split.map { |n| n =~ /(Fi|Bu)zz/ ? n : n.to_i }
end
end
ひとまずこんな形で書き換えられた。
require_relative '../fizzbuzz'
describe FizzBuzz do
before do
ARGV[0] = 15
@fizz_buzz = FizzBuzz.new
end
describe '#console' do
let(:result) {
result = ->(max) { @fizz_buzz.map_upto(max, @fizz_buzz.method(:fizzbuzz)) }
@fizz_buzz.console(result)
}
let(:ans) { "1\n2\nFizz\n4\nBuzz\nFizz\n7\n8\nFizz\nBuzz\n11\nFizz\n13\n14\nFizzBuzz\n" }
it '' do
expect { result }.to output(ans).to_stdout
end
end
end
こちらの方が後から読み返したときに分かりやすいように思います。
最終的にこうなりました(追記:2016/12/14)。