在Rspec中testingSTDOUT输出

我正在试图为这个声明build立一个规范。 用'puts'很容易,

print "'#{@file}' doesn't exist: Create Empty File (y/n)?" 

RSpec 3.0+

RSpec 3.0为此增加了一个新的output匹配器 :

 expect { my_method }.to output("my message").to_stdout expect { my_method }.to output("my error").to_stderr 

MINITEST

Minitest也有一个叫capture_io东西:

 out, err = capture_io do my_method end assert_equals "my message", out assert_equals "my error", err 

RSpec <3.0(和其他)

对于RSpec <3.0和其他框架,您可以使用以下帮助程序。 这将允许您捕获分别发送到stdout和stderr的任何内容:

 require 'stringio' def capture_stdout(&blk) old = $stdout $stdout = fake = StringIO.new blk.call fake.string ensure $stdout = old end def capture_stderr(&blk) old = $stderr $stderr = fake = StringIO.new blk.call fake.string ensure $stderr = old end 

现在,当你有一个方法,应该打印一些东西到控制台

 def my_method # ... print "my message" end 

你可以写这样的规范:

 it 'should print "my message"' do printed = capture_stdout do my_method # do your actual method call end printed.should eq("my message") end 

如果你的目标只是能够testing这种方法,我会这样做:

 class Executable def initialize(outstream, instream, file) @outstream, @instream, @file = outstream, instream, file end def prompt_create_file @outstream.print "'#{@file}' doesn't exist: Create Empty File (y/n)?" end end # when executing for real, you would do something like # Executable.new $stdout, $stdin, ARGV[0] # when testing, you would do describe 'Executable' do before { @input = '' } let(:instream) { StringIO.new @input } let(:outstream) { StringIO.new } let(:filename) { File.expand_path '../testfile', __FILE__ } let(:executable) { Executable.new outstream, instream, filename } specify 'prompt_create_file prompts the user to create a new file' do executable.prompt_create_file outstream.string.should include "Create Empty File (y/n)" end end 

不过,我想指出,我不会直接testing这样的方法。 相反,我会testing使用它的代码。 我昨天正在和一个潜在的学徒谈话,他正在做一些非常相似的事情,所以我和他坐下来,我们重新实施了一部分class级,你可以在这里看到。

我也有一个博客 ,谈论这种事情。