Ruby minitest测试输出需要用户输入的方法

时间:2014-11-11 12:48:54

标签: ruby stdin minitest assertions

分辨


问题1:我想在下面的类中为file_choice_reader编写测试。

该类将某些类型的文件列表打印到命令行,并允许用户通过键入索引号来选择一个。

class File_chooser

  #shortened for readability

  def file_choice_suggester
    file_list = file_list_generator
    if file_list.count > 0
      file_list.each_with_index do |file, index|
        puts index.to_s + ' ' + file
      end
    else 
      puts 'Neither .fcv nor .tmpl nor .ipa nor .apf files in directory.'  
    end
    file_list
  end

  def file_choice_reader
    unless File.exists? 'Cookie.txt'
      file_list = file_choice_suggester
      puts 'Choose file by typing index number!'
      chosen_file = STDIN.gets.chomp
      if /[^0-9]/.match(chosen_file) || chosen_file.to_i >= file_list.count
        abort ('No valid index number.')
      else 
        chosen_file = chosen_file.to_i
      end
      cookie_writer(  file_list[chosen_file].to_s )
      system 'cls'
      puts 'You chose file: ' + file_list[chosen_file].to_s
      path_and_file = file_list[chosen_file].to_s
    else
      self.hints_hash = hints_hash.merge( 'cookie_del' => '* Change file by typing command: del Cookie.txt *' )
      pre_chosen_file = File.read('Cookie.txt')
      path_and_file = pre_chosen_file.chomp.to_s
    end
    path_and_file
  end

end

我的测试看起来像这样(我被提示输入索引号,但它仍然说输出是“”):

class TestFile_chooser < MiniTest::Unit::TestCase 
  def setup
    @file_chooser = File_chooser.new
  end

  def test_file_choice_reader_produces_confirmation_output
    assert_output( /You chose file/ ) { @file_chooser.file_choice_reader }
  end 
end

file_choice_reader的输出始终为“”。如何添加获取用户输入和/然后/测量输出的顺序?

问题2:这是一个简短的问题。与上述相同的测试类也包含

  def test_file_choice_suggester_produces_output
    assert_output( /apf|fcv|tmpl|ipa/ ) {  @file_chooser.file_choice_suggester }
  end 

此测试通过。但它给我留下了“1次运行,2次断言”。这让我感到困惑。如何在1次运行中进行1次测试产生2(??)断言?

我会很乐意帮忙。互联网上最小的讨论似乎并未涵盖这些内容。也许这太基础了?

(我很感谢评论中关于代码的所有其他评论。感谢您的帮助。)


更新(问题1)

在下面的回复的帮助下,我使用http://www.ruby-doc.org/core-2.1.5/Module.html

中的示例进行了最新版本的测试
@file_chooser.instance_eval do 
  self.create_method( :puts ) {|arg| printed = arg} 
end

测试运行没有错误......但是......它仍然告诉我:“反驳失败。没有给出消息。”

感谢您的帮助!还要感谢所有提示如何弄明白。

[在这里添加代码很难在评论中阅读。]


更新2 (问题1)

我按照不同问题的建议明确要求最小的宝石。我把它放在我的testfile代码上面:

require 'rubygems'
gem 'minitest'
require 'minitest/autorun'
require_relative 'falcon'

(如果这是多余的,请告诉我。)

以下测试代码现在既不会产生错误也不会再出现故障:

  def test_file_choice_suggester_produces_output
    assert_output( /apf|fcv|tmpl|ipa/ ) {  @file_chooser.file_choice_suggester }
  end 

感谢大家的帮助!

1 个答案:

答案 0 :(得分:0)

对于#1:

一种方法可能是通过覆盖puts方法来删除测试所使用的IO对象。另一种方法是重构您的设计,以便您的方法更小,更容易测试。

puts覆盖将是这样的:

在你的测试中:

@file_chooser = File_chooser.new
printed = nil
@file_chooser.instance_eval do
  # Open up the instance and stub out the puts method to save to a local variable
  define_method :puts, Proc.new {|arg| printed = arg}
end
# Run code
refute printed.nil?

或者,你可以对$ STDOUT对象运行一个期望,以确保它得到正确的调用(参见Ruby的Mocha)