In writing spec in Ruby, you would often meet a situation that you have to reduce outputting messages to STDOUT.
def f p 123 end describe 'f' do it 'outputs "123\n" to stdout' do ... end end
How do you write it? Usually I assign a stringio object to
$stdout. I guess many people use this approach.
def f p 123 end # spec require 'stringio' results = $stdout = StringIO.new f() results.close_write results.rewind $stdout = STDOUT p results.read #=> "123\n"
I started having an idea that
IO#reopen may be a better solution
of it. The code previously given looks obviously dirty.
Finally I figured out the new approach was also dirty.
def f p 123 end require 'tempfile' results = Tempfile.new('a').path a = STDOUT.dup STDOUT.reopen(results, 'w') f() STDOUT.reopen(a) p File.read(results)
STDOUT.reopen doesn't accept an IO object, but only accepts a
capture_io of minitest
Eric Hodel and Ryan Davis mentioned about
minitest. It uses the former approache.
def capture_io require 'stringio' orig_stdout, orig_stderr = $stdout, $stderr captured_stdout, captured_stderr = StringIO.new, StringIO.new $stdout, $stderr = captured_stdout, captured_stderr yield return captured_stdout.string, captured_stderr.string ensure $stdout = orig_stdout $stderr = orig_stderr end