如何使用MiniTest测试记录器消息



我有一个应用程序,我想测试我是否正确来自我的记录器的消息。

一个简短的例子(您可以在log4r和logger之间切换):

gem 'minitest'
require 'minitest/autorun'
require 'log4r'
#~ require 'logger'
class Testlog < MiniTest::Test
  def setup
    if defined? Log4r
      @log = Log4r::Logger.new('log')
      @log.outputters << Log4r::StdoutOutputter.new('stdout', :level => Log4r::INFO)
    else
      @log = Logger.new(STDOUT)
      @log.level = Logger::INFO
    end
  end
  def test_silent
    assert_silent{ @log.debug("hello world") }
    assert_output(nil,nil){ @log.debug("Hello World") }
  end
  def test_output
    #~ refute_silent{ @log.INFO("Hello") }#-> NoMethodError: undefined method `refute_silent'        
    assert_output("INFO log: Hello Worldn",''){ @log.info("Hello World") }
  end
end

但我得到了:

  1) Failure:
Testlog#test_output [minitest_log4r.rb:27]:
In stdout.
Expected: "INFO log: Hello Worldn"
  Actual: ""

在我的输出屏幕上,我看到了消息。我对Log4r::StderrOutputterLog4r::Outputter.stdout有相似的结果。

因此,它似乎被发送到输出屏幕,但它并没有被STDOUT或STDERR中的minitest捕获。

在我开始写一个minitest-log4r-Gem:之前

是否有可能在minitest中测试记录器输出


如果不是:如何实现minitest-log4r-Gem有什么建议吗?

我能想象的例子:

  • 为minitest定义新的输出程序(Log4r::MinitestOutputer)
  • 嘲笑伐木工人
  • 新断言(添加新的输出程序作为参数?):
    • assert_message('INFO log: Hello World'){ @log.info("Hello World") }
    • assert_messages(:info => 1, :debug => 2){ @log.info("Hello World") }来计数消息
    • assert_info_messages('Hello World'){ @log.info("Hello World") }
    • assert_debug_messages('Hello World'){ @log.info("Hello World") }

您可以设置一个管道,将写入程序从管道传递给记录器,然后使用管道中的读取器来测试断言。

http://ruby-doc.org/core-2.1.0/IO.html#method-c管

类似于:

require 'logger'
r, w = IO.pipe
log = Logger.new(w)
log.info "testing info log message"
output = r.gets
puts "Test passed: #{!!(/testing/ =~ output)}"

与此同时,我创建了一个最小的记录器Gem

如何使用它的代码示例:

require 'log4r'
require 'minitest-logger'
class Test_log4r < MiniTest::Test
  def setup 
    @log = Log4r::Logger.new('log')
    @log.level = Log4r::INFO
  end    
  def test_output_1 
    assert_log(" INFO log: Hello Worldn"){ @log.info("Hello World") }
  end
  def test_output_regex
    assert_log(/Hello World/){ @log.info("Hello World") }
  end  
  def test_silent
    assert_silent_log(){
      @log.debug("Hello World")
      #~ @log.info("Hello World")     #uncomment this to see a failure
    }
    refute_silent_log(){
      @log.warn("Hello World")     #comment this to see a failure
    }
  end
end

在测试期间,临时输出器被添加到记录器@log。在测试之后,再次移除输出器。

gem支持log4r和logger。

@Puhlze的答案很好。仅对于非阻塞,请在手动之前检查是否有可用的输入:

if IO.select([r], [], [], 0.01).nil?

假设我们在一个名为logger.rb:的文件上有这段代码

require 'logger'
class Framework
  attr_reader :logger
  def initialize
    @logger = Logger.new("/tmp/minitest.log")
  end
end
class Custom
  def initialize(framework)
    @framework = framework
  end
  def error!
    raise StandardError, 'Forced error'
  rescue StandardError => e
    @framework.logger.error "Error: #{e}"
  end
end

我们需要测试记录器错误消息。我们可以使用stub方法和StringIO对象:

require 'minitest'
require 'minitest/autorun'
require_relative 'logger.rb'
class LoggerTest < MiniTest::Test
  def test_logger
    framework = Framework.new
    custom    = Custom.new(framework)
    io        = StringIO.new
    framework.stub :logger, Logger.new(io) do
      custom.error!
      assert_match(/Forced error/, io.string)
    end
  end
end

这样我们就不需要覆盖框架记录器,只需将其存根即可。

最新更新