如何使用gets.chomp测试函数?

我有一个使用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模拟用户输入?

您首先将该方法的两个问题分开:

 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 

至于第一个,你可以

  1. 手工测试并依赖它不会破坏(推荐的方法,TDD不是宗教)。
  2. 获取有问题的shell的颠覆版本并使其模仿用户,并比较get_action是否确实获得用户键入的内容。

虽然这是对你的问题的实际答案,但我不知道如何做2.我只知道如何模仿浏览器后面的用户( watir-webdriver )而不是shell会话后面。

您可以创建一个管道并将其“读取结束”分配给$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 

您可以注入IO依赖项。 从STDIN gets读取,这是类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,文件,网络等)进行交互。

要在生产代码中在控制台上使用它,请传入STDINSTDOUT

 require 'whatever' whatever = Whatever.new STDIN, STDOUT whatever.welcome_user puts "Your action was #{whatever.action}"