【问题标题】:Ruby minitest test output of method that requires user input需要用户输入的方法的 Ruby minitest 测试输出
【发布时间】:2014-11-11 12:48:53
【问题描述】:

已解决


问题 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 个(??)断言?

我会很高兴得到帮助。互联网上最小的讨论似乎并没有涵盖这些事情。可能太基础了吧?

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


更新(问题 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

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

感谢您到目前为止的帮助!也感谢所有提示如何弄清楚。

[此处添加代码在 cmets 中难以阅读。]


更新 2(问题 1)

我遵循了关于另一个问题的建议,明确要求使用 minitest gem。我把它放在我的测试文件代码上面:

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 

感谢大家的帮助!

【问题讨论】:

  • #2 它可能与发出多个断言的assert_output 方法有关。或者,如果您将这两个测试放在同一个文件中。
  • 就风格而言,我推荐 GitHub 的风格指南:github.com/styleguide/ruby
  • #1 不确定问题到底是什么,但应该可以删除用户输入或将输入流作为参数或其他东西传递
  • 谢谢!问题是:如何编写确保我的用户收到确认消息的测试。输出不是该方法的直接输出,而是仅在用户输入 sdtin 后出现。测试当前告诉我该方法输出一个空字符串。用户输入后情况并非如此。我需要如何编写测试? (我希望这更清楚。)

标签: ruby stdin minitest assertions


【解决方案1】:

对于#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 对象运行期望以确保它得到正确的调用(请参阅 Mocha for Ruby)

【讨论】:

  • 谢谢!不幸的是,这对我不起作用。错误消息是:falcon_test.rb:90:语法错误,意外'{',期望关键字结束定义方法,:puts {|arg| print = arg} ^ falcon_test.rb:90: 语法错误,意外'}',期待keyword_end falcon_test.rb:116: 语法错误,意外$end,期待keyword_end
  • 我将代码放入def test ....结束。不知道我做错了什么。感谢您的回复。
  • 对不起,我混淆了语法。立即尝试
  • 谢谢!在阅读了 define_method 如何是私有的并在此页面ruby-doc.org/core-2.1.5/Module.html 上重复破解后,测试运行没有错误:@file_chooser.instance_eval do self.create_method( :puts ) {|arg| print = arg} end ...但是...它仍然告诉我我的输出是“”:“在标准输出中。预期 /apf|fcv|tmpl|ipa/ 匹配“”。到目前为止谢谢。我确实学到了一些东西。感谢所有提示如何弄清楚!
  • 抱歉,混淆了错误消息。消息是:“反驳失败。没有给出消息。”
猜你喜欢
  • 2015-04-30
  • 1970-01-01
  • 2020-04-18
  • 1970-01-01
  • 1970-01-01
  • 2012-07-23
  • 2015-06-09
  • 2012-12-10
  • 1970-01-01
相关资源
最近更新 更多