如何测试与它gets.chomp的功能?如何测试与它gets.chomp的功能?(How do I

2019-05-12 09:21发布

我有使用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

Answer 1:

你先分开2所担忧的方法:

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. 获取有关壳的颠覆版本,并使其模仿用户,并且比较是否get_action确实得到什么类型的用户。

虽然这是一个实际的解决您的问题,我不知道该怎么办2,我只知道如何模仿浏览器(后面的用户watir-webdriver ),而不是shell会话后面。



Answer 2:

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


Answer 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,文件,网络等)进行交互。

要使用它在生产代码的控制台上,通过在STDINSTDOUT

require 'whatever'

whatever = Whatever.new STDIN, STDOUT
whatever.welcome_user

puts "Your action was #{whatever.action}"


文章来源: How do I test a function with gets.chomp in it?