循环测试时Rspec用户输入

时间:2014-05-21 00:50:43

标签: ruby rspec

我正在使用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模拟文档,但我很难理解。

1 个答案:

答案 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