gpt4 book ai didi

ruby - 在 Ruby 中测试标准输入

转载 作者:数据小太阳 更新时间:2023-10-29 06:43:16 25 4
gpt4 key购买 nike

我目前正在尝试测试一种基本方法,该方法从用户那里接收一些输入 (gets) 并将其输出 (puts)。经过一番研究后,我发现了一种测试标准输出流的好方法,如下所示:

def capture_standard_output(&block)
original_stream = $stdout
$stdout = mock = StringIO.new
yield
mock.string.chomp
ensure
$stdout = original_stream
end

我正在测试的方法是下面的方法,输出和输入指的是我在开始时初始化的 ivars,并指向等效的 $stdout 和 $stdin:

def ask_for_mark
ouput.puts 'What shall I call you today?'
answer = input.gets.chomp.capitalize
answer
end

现在我已经看到了一些 STDIN 的解决方案,但还没有真正理解其中的任何一个,我绝对不想复制和粘贴。我唯一“工作”的是下面的那个,但它并没有真正工作,因为当我运行 rspec 时,它会暂停并等待输入,只需按回车键,它就会通过:

  it "takes user's name and returns it" do
output = capture_standard_output { game.ask_for_name }
expect(output).to eq "What shall I call you today?"
game.input.stub(:gets) { 'joe' }
expect(game.ask_for_name).to eq 'Joe'
end

什么是测试 STDIN 的好方法?我一天中的大部分时间都在盯着屏幕(这不好,我知道)所以非常感谢一个全新的视角和一些帮助:-)

更新

对于面临类似问题的任何人,我采用了不同的(更简单的)方法。首先,我会在各自的方法中分离 IO 操作。

在输入的情况下,在测试中它可以预先填充所需的数据,因此当发送 gets 消息时,它将返回由换行符分隔的数据 \n 像这样:

input = StringIO.new("one\ntwo\n")
=> #<StringIO:0x007f88152f3510>
input.gets
=> "one\n"
input.gets
=> "two\n"
input.gets
=> nil

这有助于保持被测方法的内部结构的私有(private)性,而不会将测试与实现细节耦合。

另一种方法是简单地使用多态性并传入符合相同 api 的 Fake 或 Spy 对象,而不是调用 stdinstdout,它返回固定数据,或者在 Spy 的情况下,它注册调用。

class SpyIO
def initialize
was_called? = false
end
...
def ask_for_name
# call to stdout would normally take place
was_called? = true
end
...
end

class FakeIO
def initialize(data = [some, data])
@data = data
end

def get_user_input
# call to stdin would normally happen
@data.shift
end
...
end

每种方法都有权衡取舍,但我想我会把这些放在这里,以防有人遇到类似问题或考虑选择。

最佳答案

您可以简单地stub STDIN:

it "takes user's name and returns it" do
output = capture_standard_output { game.ask_for_name }
expect(output).to eq "What shall I call you today?"
allow(STDIN).to receive(:gets) { 'joe' }
expect(game.ask_for_name).to eq 'Joe'
end

实际上,您可以对 STDOUT 执行相同的操作,而无需更改 $stdout:

it "takes user's name and returns it" do
expect(STDOUT).to receive(:puts).with("What shall I call you today?")
allow(STDIN).to receive(:gets) { 'joe' }
expect(game.ask_for_name).to eq 'Joe'
end

关于ruby - 在 Ruby 中测试标准输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23349863/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com