結論
rspecの output
と to_stderr
の組み合わせでは、 $stderr
はテストできるが、 STDERR
はテストできない。
to_stderr
の代わりに、 to_stderr_from_any_process
を使えば STDERR
もテストできる。ただし、 to_stderr
に比べてとっても遅いらしい。
経緯
rspecにて、標準エラーに出力しているコードのテストを書こうとしたところ、to_stderr
では STDERR.puts
の出力が拾えなかった。
調査
いろいろ試したところ、 $stderr.puts
や warn
の出力は to_stderr
で拾うことができた。
調査結果
こちらによれば、 to_stdout
や to_stderr
は $stdout
や $stderr
を一時的に置き換える働きをするので、 STDOUT
や STDERR
に対しては利用できない、とのこと。
to_stdout_from_any_process
や to_stderr_from_any_process
であれば、 STDOUT
や STDERR
に対しても利用できる模様。ただし、 to_stdout
や to_stderr
に比べてとても遅いらしい。
サンプルコード
# coding: utf-8
describe '標準エラーへの出力' do
context '$stderr(to_stderr)'do
it do
expect { $stderr.print 'error via $stderr' }.to output('error via $stderr').to_stderr
end
end
context 'STDERR(to_stderr)' do
it do
expect { STDERR.print 'error via STDERR' }.to output('error via STDERR').to_stderr
end
end
context '$stderr(to_stderr_from_any_process)'do
it do
expect { $stderr.print 'error via $stderr' }.to output('error via $stderr').to_stderr_from_any_process
end
end
context 'STDERR(to_stderr_from_any_process)' do
it do
expect { STDERR.print 'error via STDERR' }.to output('error via STDERR').to_stderr_from_any_process
end
end
end
サンプルコードの実行結果
% bundle exec rspec
.error via STDERRF..
Failures:
1) 標準エラーへの出力 STDERR(to_stderr) should output "error via STDERR" to stderr
Failure/Error: expect { STDERR.print 'error via STDERR' }.to output('error via STDERR').to_stderr
expected block to output "error via STDERR" to stderr, but output nothing
# ./spec/stderr_spec.rb:10:in `block (3 levels) in <top (required)>'
Finished in 0.03459 seconds (files took 0.11677 seconds to load)
4 examples, 1 failure
Failed examples:
rspec ./spec/stderr_spec.rb:9 # 標準エラーへの出力 STDERR(to_stderr) should output "error via STDERR" to stderr
サンプルコードの実行結果より、 STDERR
と to_stderr
の組み合わせのとき、標準エラーが拾えていないことがわかる。