我正在使用RSpec测试我的石头剪刀游戏。我的begin_game
函数中包含以下代码:
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
我正在尝试测试不同的user_inputs。我试过这个:
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
但这导致输出到终端的“请选择有效选择...”的无限循环。我阅读了RSpec模拟文档,但我很难理解。
答案 0 :(得分:2)
循环的原因是new_game.stub(:gets) { "r" }
总是会返回r
,无论你调用它多少次。因此user_input
永远不会包含有效输入,您的测试将永远运行。
要解决此问题,您应该在经过一定次数的尝试后让new_game#gets
返回有效选区。
例如,
new_game.stub(:gets) do
@counter ||= 0
response = if @counter > 3 # an arbitrary threshold
"rock"
else
"r"
end
@counter += 1
response
end
这会导致您的测试打印Please choose a valid selection...
4次然后终止。
根据您实施RockPaperScissors#begin_game
的方式,您编写的测试仍然无法通过。这是因为puts("a string")
将始终返回nil
。此外,while
循环也会返回nil
。因此,上面的代码片段不会返回字符串"Please choose a valid selection : rock, paper, or scissors"
。
将传递的begin_game
的实现是:
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
但是在那时,我可能会将其重命名为handle_move
,并让它接受一个参数作为参数,以避免首先发现gets
。
def handle_move(input)
if choices.include? input
"Great move!"
else
"Please choose a valid selection : rock, paper, or scissors"
end
end