2016-02-21 3 views
2

Я пытаюсь понять, какой лучший способ проверить цикл while в rspec.Пока петли в rspec

Я разрешаю пользователю вводить тип игры, в которую он/она хотел бы играть.

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 

Спасибо за вашу помощь

ответ

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 также включает в себя Введите тип игры, которую вы хотели бы сыграть (человеческий против человека, компьютер против компьютера или человека против компьютера):, которого мы не заботимся.

1

, что происходит в том, что ваш метод 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

Посмотреть этот SO ответ, если вы не используете RSpec 3.0 Testing STDOUT output in Rspec

Смежные вопросы