RSpec 的未定义方法“capture”

问题描述 投票:0回答:2

我正在尝试编写一个规范来测试显示井字游戏板。我正在使用方法

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
ruby rspec
2个回答
1
投票

问题是

#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'

(但是,如果您忘记这种方法并只是将您的板构建为字符串,那么您的生活会更轻松。)


0
投票

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
© www.soinside.com 2019 - 2024. All rights reserved.