【问题标题】:While loops in rspecrspec中的while循环
【发布时间】:2016-02-22 07:54:10
【问题描述】:

我试图了解在 rspec 中测试 while 循环的最佳方法是什么。

我允许用户输入他/她想玩的游戏类型。

def get_action
    gets.strip.downcase
end

def type_of_game
    puts "Enter the type of game you would like to play (human v. human, computer v. computer, or human v. computer):"
    gametype = get_action
    until (gametype == "human v. human" || gametype == "computer v. computer" || gametype == "human v. computer")
        puts "Please enter a valid game"
        gametype = get_action
    end
    return gametype
end

目前我在 rspec 中有这个,但它会导致无限循环

require "minitest/spec"  
require "minitest/autorun"


describe Game do 
   before :each do
    @game = Game.new    
   end


   it "should prompt to user to enter their gametype again if not human v. human, computer v. computer, or human v. compouter" do
      def @game.get_action; "human v. machine" end
      expect(@game.type_of_game).to eql("Please enter a valid game")
   end

感谢您的帮助

【问题讨论】:

    标签: ruby rspec


    【解决方案1】:

    我将重写它如下,因为它允许我们存根loop 并屈服(从而避免您遇到的无限循环问题)。这种方法的一个警告是,您将收到游戏类型“人与机器”,因为它在一次迭代后产生。

    class Game
      def get_action
        gets.strip.downcase
      end
    
      def type_of_game
        puts 'Enter the type of game you would like to play (human v. human, computer v. computer, or human v. computer):'
        gametype = get_action
        loop do
          break if gametype == 'human v. human' || gametype == 'computer v. computer' || gametype == 'human v. computer'
          puts 'Please enter a valid game'
          gametype = get_action
        end
    
        gametype
      end
    end
    

    Rspec (3.3.0)

    require_relative 'path/to/game'
    
    describe Game do
      subject { Game.new }
    
      it 'prompts the user to enter their gametype again if it is incorrect' do
        allow(subject).to receive(:gets).and_return('human v. machine')
        allow(subject).to receive(:loop).and_yield
    
        expect { subject.type_of_game }
          .to output(/Please enter a valid game/)
          .to_stdout
      end
    
      it 'does not prompt the user to enter their gametype if it is correct' do
        allow(subject).to receive(:gets).and_return('human v. human')
    
        expect { subject.type_of_game }
          .to_not output(/Please enter a valid game/)
          .to_stdout
      end
    
      it 'returns the specified gametype if valid' do
        allow(subject).to receive(:gets).and_return('human v. human')
    
        expect(subject.type_of_game).to eq('human v. human')
      end
    end
    

    我使用正则表达式匹配器 (//) 的原因是因为stdout 还包括 输入您想玩的游戏类型(人类与人类、计算机与计算机或人类 v .computer):我们不关心。

    【讨论】:

      【解决方案2】:

      发生的情况是您的方法get_action 已被存根以不断返回无效响应。 (干得好!)

      所以你的type_of_game 方法会反复调用get_action,一遍又一遍。

      您要测试的是您的type_of_game 方法是否正确地向用户发送了一条消息。

      要在 rspec (3.0) 中执行此操作,您可以像这样使用 output 匹配器:

      expect { @game.type_of_game }.to output("Please enter a valid game").to_stdout

      如果您不使用 rspec 3.0 Testing STDOUT output in Rspec,请查看此 SO 答案

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-02
        • 1970-01-01
        • 1970-01-01
        • 2016-04-24
        • 2016-11-27
        • 1970-01-01
        • 1970-01-01
        • 2014-03-29
        相关资源
        最近更新 更多