2015-04-16 54 views
1

我在Ruby中和類「遊戲」的構造函數中編寫了Mastermind遊戲,我想使用gets.chomp來詢問用戶名稱。相當容易,但是我遇到麻煩的地方是在RSpec中測試這個類時,但我似乎無法正確地存取'gets'和'puts',因爲它們在構造函數中不是常規方法。Rspec - 從構造函數中取出gets.chomp

class Game 
    def initialize 
    puts "Please enter your name:" 
    @player = Player.new(gets.chomp) 
    end 
end 

describe Game do 
    Game.stub(:gets).and_return("Create Code AI") 
    Game.stub(:puts) 
    subject(:game) { Game.new } 

    describe "#new" do 
    its("player.name") { eql("Create Code AI") } 
    end 
end 

class Player 
    attr_reader :name 

    def initialize(name) 
    @name = name 
    end 
end 

我也試圖把存根到「之前」和「讓」除其他事項外塊,但似乎沒有任何工作。任何幫助表示讚賞!

+0

雖然這當然是可能的,你應該考慮重構你的代碼。如果你可以初始化一個'Game'並且不會扼殺'gets'和'puts',這會不會容易得多? – Stefan

+0

我認爲這是最好的方式去做,謝謝!下面的答案雖然可能是正確的,但對我所做的事情來說似乎太複雜了。 –

回答

1

我有捕獲標準輸入和標準輸出的方法,以幫助像這樣的情況下測試:

require 'stringio' 

module Kernel 
    def capture_stdout(console_input = '') 
    $stdin = StringIO.new(console_input) 
    out = StringIO.new 
    $stdout = out 
    yield 
    return out.string.strip 
    ensure 
    $stdout = STDOUT 
    $stdin = STDIN 
    end 
end 

現在,讓我們假設我想測試與標準輸入/輸出交互的方法:

def greet 
    name = gets 
    puts "Welcome, #{name}!" 
end 

我會寫下面的測試:

require 'rspec/autorun' 

RSpec.describe '#say_name' do 
    it 'prints name correctly' do 
    input = 'Joe' 
    result = capture_stdout(input) do 
     greet 
    end 

    expect(result).to eql 'Welcome, Joe!' 
    end 
end 

我介紹了上面的例子來說明如何測試控制檯輸入和輸出。

在你的情況下,測試可能是這樣的:

describe Game do 
    subject(:game) do 
    capture_stdout('Create Code AI') { return Game.new } 
    end 

    describe "#new" do 
    its("player.name") { eql("Create Code AI") } 
    end 
end 

注:爲了使這一工作,#player應該是Game可訪問成員。所以,你可能要添加到您的Game類:

attr_reader :player 
+1

謝謝! 這似乎對我所做的雖然(我有點理解它,但不是100%)太複雜,所以我想我會去與其他人的評論,並採取puts +從構造函數中拿出並把他們到不同的方法,這應該是更容易存根。 –

+0

@FrankPeelen是的,這是很好的建議。當沒有其他選擇時,存根'gets'和'puts'(例如:存在您需要測試的現有遺留代碼)。我個人使用這種技術爲codegolf.stackexchange.com寫出了答案,當我明確地使用stdin/out時。 – GolfWolf

相關問題