Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

undefined method `capture' for RSpec

Tags:

ruby

rspec

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
like image 504
Steven Aguilar Avatar asked Sep 12 '26 00:09

Steven Aguilar


1 Answers

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.)

like image 185
struthersneil Avatar answered Sep 13 '26 14:09

struthersneil



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!