我有一个使用gets.chomp这样的简单函数:
def welcome_user
puts "Welcome! What would you like to do?"
action = gets.chomp
end
我想使用ruby
内置的TestCase
套件对其进行测试,如下所示:
class ViewTest < Test::Unit::TestCase
def test_welcome
welcome_user
end
end
问题是,当我运行该测试时,gets.chomp
会停止测试,因为它需要用户输入某些内容。有没有办法只使用ruby
模拟用户输入?
答案 0 :(得分:13)
您可以创建pipe并将其“读取结束”分配给$stdin
。写入管道的“写入结束”然后模拟用户输入。
这是一个用于设置管道的小辅助方法with_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 :(得分:7)
您首先要分离方法的两个问题:
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
然后你分别测试第二个。
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
至于第一个,你可以
get_action
确实得到了用户输入的内容。虽然这是对你的问题的实际答案,但我不知道如何做2.我只知道如何模仿浏览器后面的用户(watir-webdriver
)而不是shell会话后面。
答案 2 :(得分:3)
您可以注入IO依赖项。 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
试验:
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
这允许您的类与任何IO流(TTY,文件,网络等)进行交互。
要在生产代码中的控制台上使用它,请传入STDIN
和STDOUT
:
require 'whatever'
whatever = Whatever.new STDIN, STDOUT
whatever.welcome_user
puts "Your action was #{whatever.action}"