Reputation: 275
Here's the method that's giving the error/falure:
def draw?(board)
if full?(board) == true && won?(board) == false
return true
else
return false
end
end
The method does everything is supposed to do but this is the error that appears when I run the rspec file:
1) ./lib/tic_tac_toe.rb #draw? calls won? and full?
Failure/Error: expect(self).to receive(:won?).with(board)
(#<RSpec::ExampleGroups::LibTicTacToeRb::Draw:0x00000002e300b0>).won?(["X", "O", "X", "O", "X", "X", "O", "X", "O"])
expected: 1 time with arguments: (["X", "O", "X", "O", "X", "X", "O", "X", "O"])
received: 0 times
Here's the rspec test:
describe '#draw?' do
it 'calls won? and full?' do
board = ["X", "O", "X", "O", "X", "X", "O", "X", "O"]
expect(self).to receive(:won?).with(board)
expect(self).to receive(:full?).with(board)
draw?(board)
end
Essentially, I read: #draw? fails to call #full? and #won?
But when I look at my #draw? method, I do call them! as the "if" conditional!
So where am I going wrong?
Help is greatly appreciated!
I'm currently learning Ruby.
Upvotes: 0
Views: 178
Reputation: 2468
1) Your entire draw?
method can be simplified to one line: full?(board) && !won?(board)
2) Your need your expect
to be spying on an instance of the class, or the class itself if you're testing class methods. You're using self
which will be RSpec itself, not the underlying class you're testing. Since I don't know the name of it, I'll assume it's called Game
. Try something like this:
describe '#draw?' do
it 'calls draw? and full?' do
board = ["X", "O", "X", "O", "X", "X", "O", "X", "O"]
game = Game.new
expect(game).to receive(:won?).with(board)
expect(game).to receive(:full?).with(board)
game.draw?
end
end
3) Another issue here is that you're expecting both methods to be called, but won?
won't be called if full?
returns false
. This is due to short circuiting. In situations where all statements must evaluate to true (or false), once one of them does not, the rest are not evaluated. Think of an example like: if user != nil && user.admin?
. You want short-circuiting here so that the second statement does not get evaluated if the first isn't true. And in general it's an unnecessary use of resources to evaluate statements whose output doesn't matter.
4) Lastly, in general you're best off testing the output of the function rather than the internals of how it works. Better off having a bunch of tests where you pass in data and then expect
a result.
Upvotes: 1