我有一个这样的Ruby类:
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。
6条答案
按热度按时间vi4fp9gy1#
神奇的是使用capture_subprocess_io
字符串
b09cbbtk2#
MiniTest的
#capture_io
临时切换$stdout
和$stderr
的StringIO
对象,以捕获写入$stdout
或$stderr
的输出。但Logger
有自己的原始标准错误流引用,它会愉快地写入。我认为你可以认为这是一个bug,或者至少是MiniTest的#capture_io
的限制。在您的例子中,您正在使用参数
STDERR
在块内创建Logger
到#capture_io
。STDERR
仍然指向原始标准错误流,这就是为什么它不能按预期工作的原因。将
STDERR
更改为$stderr
(此时 * 确实 * 指向StringIO
对象)可以解决这个问题,但只有当Logger实际上是在#capture_io
块中创建的,因为在该块之外,它指向原始的标准错误流。字符串
bzzcjhmw3#
capture_subprocess_io文档
基本上,伦纳德的例子用工作代码和指向文档来充实和注解。
将$stdout和$stderr捕获到字符串中,使用Tempfile确保子进程IO也被捕获。
字符串
注意:这个方法比#capture_io慢大约10倍,所以只在需要测试子进程的输出时使用。
See Documentation
uurv41yg4#
很晚了,但这是对先前答案的回应:
https://stackoverflow.com/a/27717477/19637807
在利用StringIO的基础上,我们可以使用minitest和mocha来做这样的事情:
字符串
这确保了在被调用用于测试的函数中的任何
Logger.new
示例化都将被StringIO示例替换用于输出。因此,您根本不需要修改底层函数的日志记录器实现!我使用Jikku的答案成功地对一个ruby lambda函数进行了单元测试,评估了它的预期日志输出:
型
oipij1gg5#
这是一个老问题,但我们这样做的一种方法是用一个expects来模拟记录器。
第一个月
这允许我们Assert测试中的代码,而不改变logger的工作方式。
作为
capture_io
的一个例子,我们有一个logger实现,允许我们传入哈希值并将其输出到json。当我们测试该实现时,我们使用capture_io
。这是可能的,因为我们在主题行中使用$stdout
初始化了logger实现。subject { CustomLogging.new(ActiveSupport::Logger.new($stdout)) }
个在测试中
字符串
iyzzxitl6#
在初始化
Logger.new
以捕获输出时,您需要提供一个不同的StringIO
对象,而不是通常的:STDERR
,它实际上指向控制台。我修改了上面的两个文件,并将其合并为一个文件,以便您可以轻松地复制和测试:
字符串
说明:
1.方法
do_something
在没有参数的情况下使用时,将在所有其他代码中正常运行。1.当提供
StringIO
方法时,它使用该方法而不是典型的STDERR
,从而能够捕获输出,例如将其捕获到文件中或在本例中用于测试。