我正在尝试编写一个规范来测试显示井字游戏板。我正在使用方法
capture
但当我运行规范时它会抛出错误。我正在使用捕获来获取方法调用的输出。 https://apidock.com/rails/Kernel/capture
这是我的方法:
def display_board
puts " #{grid[0]} | #{grid[1]} | #{grid[2]} "
puts "-----------"
puts " #{grid[3]} | #{grid[4]} | #{grid[5]} "
puts "-----------"
puts " #{grid[6]} | #{grid[7]} | #{grid[8]} "
end
这是我的 Rspec 测试:
context "#display_board" do
output = capture(:stdout) { board.display_board}
rows = output.split("\n")
binding.pry
expect(rows[0]).to eq(" | | ")
expect(rows[1]).to eq("-----------")
expect(rows[2]).to eq(" | | ")
expect(rows[3]).to eq("-----------")
expect(rows[4]).to eq(" | | ")
end
问题是
#capture
已被弃用并删除。
就我个人而言,我会将 I/O 与游戏内容的生成分开,因为这样更容易使用和测试。因此,不用
puts
,只需构建一个包含您的板的字符串(每行末尾有一个 \n
)并测试其正确性。在实际游戏中,通过一次 puts
调用将棋盘输出到控制台。
如果你真的想捕获STDOUT,有一种方法。
$stdout
是一个全局变量,包含对当前 STDOUT 流的引用。默认情况下,它始终设置为 STDOUT
,一个表示程序实际 STDOUT 的常量,但您可以将 $stdout
重定向到另一个 IO 流,例如 StringIO
对象。 puts
将写入 $stdout
所指的任何内容,而不是直接写入 STDOUT
(那里有细微的差别!)。
$stdout = StringIO.new
puts 'this is my output'
captured_output = $stdout.string
$stdout = STDOUT # restore it when you're done
现在您已经在
captured_output
中捕获了“这是我的输出”(后跟换行符)。但此时您还会有其他任何内容进入 STDOUT,因此它并不理想(例如 ruby 控制台中的控制台输出)。您应该将其包装在确保其始终恢复的方法中,例如
def capture()
$stdout = StringIO.new
yield
$stdout.string
ensure
$stdout = STDOUT
end
您可以将其与块一起使用,例如
capture { puts 'xyz' }
=> 'xyz\n'
(但是,如果您忘记这种方法并只是将您的板构建为字符串,那么您的生活会更轻松。)
capture
已从 Rails 中删除,但我喜欢它并将其带回来,主要用于我的规范套件中。我提取了确切的 Rails 代码以及完整的测试套件,然后改进了测试套件。该 gem 称为 silent_stream
,它适用于 Rails 5、6 和 7,您可以在这里找到它:https://github.com/pboling/silent_stream
这就是你的使用方法:
# Make the methods avaialble:
RSpec.configure do |conf|
conf.include SilentStream
end
# Then add an expectation on output:
it 'has output' do
output = capture(:stdout) { subject.request(:get, '/success') }
logs = [
'INFO -- request: GET https://api.example.com/success',
'INFO -- response: Status 200'
]
expect(output).to include(*logs)
end