2013-06-05 9 views
7

私はこのようなgets.chomp使用して、簡単な機能があります。gets.chompで関数をテストするにはどうすればよいですか?

def welcome_user 
    puts "Welcome! What would you like to do?" 
    action = gets.chomp 
end 

を私はこのようなTestCaseスイートに建てruby年代使用してそれをテストしたいと思います:

class ViewTest < Test::Unit::TestCase 
    def test_welcome 
     welcome_user  
    end 
end 

を問題があり、そのテストを実行すると、ユーザーが何かを入力する必要があるため、gets.chompがテストを停止します。 rubyを使用してユーザー入力をシミュレートする方法はありますか?

def get_action 
    gets.chomp 
end 

def welcome_user 
    puts "Welcome to Jamaica and have a nice day!" 
    action = get_action 
    return "Required action was #{action}." 
end 

をそして、あなたは別に秒1をテスト:

答えて

7

あなたは第一の方法の2つの懸念を分離します。最初のものについては

require 'minitest/spec' 
require 'minitest/autorun' 

describe "Welcoming users" do 
    before do 
    def get_action; "test string" end 
    end 

    it "should work" do 
    welcome_user.must_equal "Required action was test string." 
    end 
end 

、あなたは手で

  1. テストをすることができますし、それは(TDDは宗教ではない、推奨されるアプローチ)を壊さないことを依存しています。
  2. 疑わしいシェルの下位バージョンを取得し、それをユーザーに模倣させて、が実際にユーザーが入力したものを取得するかどうかを比較してください( )。

これはあなたの問題への実用的な答えですが、私は2を行う方法がわからない、私はシェルのセッションの後ろではない(watir-webdriver)ブラウザの後ろにユーザーを模倣する方法を知っていると。

12

pipeを作成し、その「読み取り終了」を$stdinに割り当てることができます。パイプの「書き込み終了」に書き込むと、ユーザーの入力がシミュレートされます。

require 'test/unit' 

class View 
    def read_user_input 
    gets.chomp 
    end 
end 

class ViewTest < Test::Unit::TestCase 
    def test_read_user_input 
    with_stdin do |user| 
     user.puts "user input" 
     assert_equal(View.new.read_user_input, "user input") 
    end 
    end 

    def with_stdin 
    stdin = $stdin    # remember $stdin 
    $stdin, write = IO.pipe # create pipe assigning its "read end" to $stdin 
    yield write    # pass pipe's "write end" to block 
    ensure 
    write.close    # close pipe 
    $stdin = stdin    # restore $stdin 
    end 
end 
+1

Thnaksをその 'IO.pipe'のために、あなたはそこに私に何かを教えました。 –

+0

ありがとうございました、アプローチが気に入りました! –

3

あなたはIOの依存関係を注入できます。

は、ここでパイプを設定するための小さなヘルパーメソッドwith_stdinとの例を示します。 getsは、STDINから読み取ります。これは、クラスIOです。 IOオブジェクトをクラスに追加する場合は、テストでStringIOを使用できます。このような何か:

class Whatever 
    attr_reader :action 

    def initialize(input_stream, output_stream) 
    @input_stream = input_stream 
    @output_stream = output_stream 
    end 

    def welcome_user 
    @output_stream.puts "Welcome! What would you like to do?" 
    @action = get_input 
    end 

private 

    def get_input 
    @input_stream.gets.chomp 
    end 

end 

テスト:これは、あなたのクラスは、任意のIOストリーム(TTY、ファイル、ネットワークなど)と対話することができます

require 'test/unit' 
require 'stringio' 
require 'whatever' 

class WhateverTest < Test::Unit::TestCase 
    def test_welcome_user 
    input = StringIO.new("something\n") 
    output = StringIO.new 
    whatever = Whatever.new(input, output) 

    whatever.welcome_user 

    assert_equal "Welcome! What would you like to do?\n", output.string 
    assert_equal "something", whatever.action 
    end 
end 

は、生産コードでコンソール上でそれを使用するには、STDINSTDOUTに渡します

require 'whatever' 

whatever = Whatever.new STDIN, STDOUT 
whatever.welcome_user 

puts "Your action was #{whatever.action}" 
関連する問題