我有一个像这样的红宝石课:
require 'logger'
class T
def do_something
log = Logger.new(STDERR)
log.info("Here is an info message")
end
end
测试脚本排成一行:
#!/usr/bin/env ruby
gem "minitest"
require 'minitest/autorun'
require_relative 't'
class TestMailProcessorClasses < Minitest::Test
def test_it
me = T.new
out, err = capture_io do
me.do_something
end
puts "Out is '#{out}'"
puts "err is '#{err}'"
end
end
当我运行此测试时,out和err都是空字符串。我看到消息打印在stderr上(在终端上)。有没有办法让Logger和capture_io很好地一起玩?
我处于直接的Ruby环境中,而不是Ruby on Rails。
答案 0 :(得分:5)
MiniTest的#capture_io
暂时切换$stdout
和$stderr
StringIO
个对象,以捕获写入$stdout
或$stderr
的输出。但是Logger
有自己对原始标准错误流的引用,它会愉快地写入。我认为你可以认为这是一个错误或至少是MiniTest #capture_io
的限制。
在您的情况下,您使用参数Logger
在块#capture_io
内创建STDERR
。 STDERR
仍然指向原始标准错误流,这就是它无法按预期工作的原因。
将STDERR
更改为$stderr
(其中 指向StringIO
个对象)可以解决此问题,但前提是Logger实际上是在#capture_io
块中创建,因为在该块之外它指向原始标准错误流。
class T
def do_something
log = Logger.new($stderr)
log.info("Here is an info message")
end
end
答案 1 :(得分:5)
神奇的是使用capture_subprocess_io
out, err = capture_subprocess_io do
do_stuff
end
答案 2 :(得分:1)
基本上伦纳德的例子充实了工作代码并指向文档(不允许编辑!)
out, err = capture_subprocess_io do
system "echo Some info"
system "echo You did a bad thing 1>&2"
end
assert_match %r%info%, out
assert_match %r%bad%, err
答案 3 :(得分:0)
这是一个老问题,但我们这样做的一种方法是用期望值模拟记录器。类似的东西
logger.expects(:info).with("Here is an info message")
这允许我们在不改变记录器开箱即用的情况下断言被测代码。
以 capture_io
为例,我们有一个记录器实现,允许我们传入哈希值并将它们输出到 json。当我们测试该实现时,我们使用 capture_io
。这是可能的,因为我们在主题行中使用 $stdout
初始化记录器实现。
subject { CustomLogging.new(ActiveSupport::Logger.new($stdout)) }
在测试中
it 'processes a string message' do
msg = "stuff"
out, err = capture_io do
subject.info(msg)
end
out.must_equal "#{msg}\n"
end
答案 4 :(得分:-1)
在初始化StringIO
以捕获输出时,您需要提供不同的Logger.new
对象,而不是通常指向控制台的STDERR
。
我稍微修改了上面两个文件,并将其制作成一个文件,以便您可以轻松复制和测试:
require 'logger'
require 'minitest'
class T
def do_something(io = nil)
io ||= STDERR
log = Logger.new io
log.info("Here is an info message")
end
end
class TestT < Minitest::Test
def test_something
t = T.new
string_io = StringIO.new
t.do_something string_io
puts "Out: #{string_io.string}"
end
end
Minitest.autorun
说明:
do_something
将在所有其他代码中正常运行。StringIO
方法时,它使用该方法而不是典型的STDERR
,从而能够将输出捕获到文件中,或者在这种情况下进行测试。