Reputation: 485
I am using RSpec to test my rock paper scissors game. Included in my begin_game
function I have the following code:
user_input = gets.chomp.downcase.to_sym
while !choices.include? user_input
puts "Please choose a valid selection : rock, paper, or scissors"
user_input = gets.chomp.downcase.to_sym
end
I am trying to test for different possible user_inputs. I have tried this:
let(:new_game) {RockPaperScissors.new}
.......
context 'validate that the user input is one of the given choices' do
it 'should prompt the user for a new input if the original one is invalid' do
new_game.stub(:gets) {"r"}
expect(new_game.begin_game).to eq("Please choose a valid selection : rock, paper, or scissors")
end
end
but this results in an infinite loop of "Please choose a valid selection ..." being outputted to Terminal. I read the RSpec mocking documentation but it was difficult for me to understand.
Upvotes: 2
Views: 1554
Reputation: 4982
The reason why it's looping is because new_game.stub(:gets) { "r" }
will always return r
no matter how many times you call it. Thus user_input
will never contain valid input and your test will run forever.
To fix this, you should make new_game#gets
return a valid selection after a certain number of tries.
For example,
new_game.stub(:gets) do
@counter ||= 0
response = if @counter > 3 # an arbitrary threshold
"rock"
else
"r"
end
@counter += 1
response
end
This would cause your test to print Please choose a valid selection...
4 times and then terminate.
Depending on how you implemented RockPaperScissors#begin_game
, the test you wrote would still not pass. This is because puts("a string")
will always return nil
. Moreover, a while
loop will also return nil
. So at no point would the above snippet of code return the string "Please choose a valid selection : rock, paper, or scissors"
.
An implementation of begin_game
that would pass is:
def begin_game
user_input = gets.chomp.downcase.to_sym
if choices.include? user_input
# return something here
else
"Please choose a valid selection : rock, paper, or scissors"
end
end
but at that point, I would probably rename it to handle_move
, and have it accept an argument as a parameter to avoid stubbing gets
in the first place.
def handle_move(input)
if choices.include? input
"Great move!"
else
"Please choose a valid selection : rock, paper, or scissors"
end
end
Upvotes: 3