I am trying to write a spec to test displaying a tic-tac-toe board. I am using the method capture but it throws an error when I run the spec. I am using capture to get the output of a method call. https://apidock.com/rails/Kernel/capture
Here is my method:
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
Here is my Rspec test:
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
The problem is that #capture was deprecated and removed.
Personally, I would separate I/O from the generation of the game content, because it's easier to work with and test that way. So instead of puts, just build up a string containing your board (with a \n at the end of each line) and test that for correctness. In the actual game, output the board to the console with one puts call.
If you really want to capture STDOUT, there is a way. $stdout is a global containing a reference to the current STDOUT stream. By default this is always set to STDOUT, a constant representing the actual STDOUT of the program, but you can redirect $stdout to another IO stream, for example a StringIO object. puts will write to whatever $stdout refers to instead of directly writing to STDOUT (there is a subtle difference there!).
$stdout = StringIO.new
puts 'this is my output'
captured_output = $stdout.string
$stdout = STDOUT # restore it when you're done
Now you have 'this is my output' (followed by a newline character) captured in captured_output. But you'll also have anything else that went to STDOUT in that time, so it's not ideal (e.g. console output in your ruby console). You should wrap that in a method that ensures it's always restored, e.g.
def capture()
$stdout = StringIO.new
yield
$stdout.string
ensure
$stdout = STDOUT
end
You can use this with a block, e.g.
capture { puts 'xyz' }
=> 'xyz\n'
(But you'll have an easier life if you forget this approach and just build your board up as a string.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With