ruby 在 Rspec 中测试 STDOUT 输出
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16507067/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Testing STDOUT output in Rspec
提问by user2292710
I am trying to build a spec for this statement. It is easy with 'puts'
我正在尝试为此声明构建规范。'puts'很容易
print "'#{@file}' doesn't exist: Create Empty File (y/n)?"
回答by Patrick Oscity
RSpec 3.0+
RSpec 3.0+
RSpec 3.0 added a new outputmatcherfor this purpose:
RSpec 3.0为此添加了一个新的output匹配器:
expect { my_method }.to output("my message").to_stdout
expect { my_method }.to output("my error").to_stderr
Minitest
迷你测试
Minitest also has something called capture_io:
Minitest 也有一个叫做capture_io:
out, err = capture_io do
my_method
end
assert_equals "my message", out
assert_equals "my error", err
RSpec < 3.0 (and others)
RSpec < 3.0(和其他)
For RSpec < 3.0 and other frameworks, you can use the following helper. This will allow you to capture whatever is sent to stdout and stderr, respectively:
对于 RSpec < 3.0 和其他框架,可以使用以下 helper。这将允许您分别捕获发送到 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
Now, when you have a method that should print something to the console
现在,当你有一个方法应该打印一些东西到控制台时
def my_method
# ...
print "my message"
end
you can write a spec like this:
你可以写一个这样的规范:
it 'should print "my message"' do
printed = capture_stdout do
my_method # do your actual method call
end
printed.should eq("my message")
end
回答by Joshua Cheek
If your goal is only to be able to test this method, I would do it like this:
如果您的目标只是能够测试此方法,我会这样做:
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
However, I want to point out that I would not test a method like this directly. Instead, I'd test the code that uses it. I was talking with a potential apprentice yesterday, and he was doing something very similar, so I sat down with him, and we reimplemented a portion of the class, you can see that here.
但是,我想指出的是,我不会直接测试这样的方法。相反,我会测试使用它的代码。昨天我正在和一个潜在的学徒交谈,他正在做一些非常相似的事情,所以我和他坐下来,我们重新实现了课程的一部分,你可以在这里看到。
I also have a blogthat talks about this kind of thing.
我也有一个博客谈论这种事情。

