【问题标题】:Write Ruby Test::Unit Errors & Fails to File编写 Ruby Test::Unit 错误和无法归档
【发布时间】:2011-08-17 20:22:15
【问题描述】:

我正在尝试将测试中发生的失败和错误写入日志文件,以便它们不会出现在屏幕上,但看起来好像错误和断言失败写入 STDOUT 而不是 STDERR。经过数小时的谷歌搜索,我无法找到有关如何重定向此输出的信息,非常感谢帮助。

【问题讨论】:

  • 您有特殊的日志记录,还是您的意思是常规输出?您可以启动您的测试脚本并在操作系统级别进行重定向。示例:'mytests.rb > log.txt'

标签: ruby unit-testing stdout stderr testunit


【解决方案1】:

为什么错误不应该出现在标准输出上? 到目前为止,我还没有准备好的解决方案来抑制特定错误的输出。

如果您接受未更改的输出,我有一个将错误和失败存储在文件中的解决方案。为通知创建第二个文件没有问题...

gem 'test-unit'
require 'test/unit'

module Test
  module Unit
    class TestSuite
      alias :old_run :run
      def run(result, &progress_block)
        old_run(result, &progress_block)
        File.open('test.log', 'w'){|f|
          result.faults.each{|err|
            case err
              when Test::Unit::Error, Test::Unit::Failure
                f << err.long_display
                f << "\n===========\n"
              #not in log file
              when Test::Unit::Pending, Test::Unit::Notification, Test::Unit::Omission
              end
          }
        }
      end
    end
  end
end


class MyTest < Test::Unit::TestCase

  def test_1()
    assert_equal( 3, 1+1) #failure
  end
  def test_2()
    1 / 0 #force an error
  end
  def test_3()
    notify 'sss'
  end
  def test_4()
    pend "MeineKlasse.new"
  end
  def test_5
    omit 'aaa' if RUBY_VERSION == '1.9.2'
  end

  def test_5
    assert_in_delta( 0.1, 0.00001, 1.0/10)
  end

end

【讨论】:

  • 谢谢!这就是我要找的。我认为必须有某种方法来更改对 Test::Unit 失败和错误的处理,但我在文档中找不到任何对它的引用。
【解决方案2】:

您是否尝试过将输出重定向到 StringIO,以便稍后将其写入日志文件?

original_stdout = $stdout
original_stderr = $stderr
fake_stdout = StringIO.new
fake_stderr = StringIO.new

$stdout = fake_stdout
$stderr = fake_stderr

然后在你运行测试之后:

$stdout = original_stdout
$stderr = original_stderr

@stdout = fake_stdout.string
@stderr = fake_stderr.string

虽然我不确定这是否可行...

【讨论】:

  • 感谢您提及这一点!我遇到了一些 test/unit 测试用例,它们一直在我背后做这样的事情,而且它正在使用 fakefs gem,所以写入日志文件已经失败(当我尝试使用 debugger gem 时,它没有大概是因为 stderr 和 stdout 是伪造的)。在我意识到我可以简单地做之前把我的头发拉出来:STDOUT.puts 'hello world'
【解决方案3】:

我希望我理解你的问题是正确的。

你的意思是这样的:

gem 'test-unit'
require 'test/unit'

class StdOutLogger < IO
  def initialize(*)
    super
    @file = File.open('log.txt', 'w')
    @stdout = true
  end 
  #write to stdout and file
  def write(s)
    $stdout << s
    @file << s
  end
end
STDOUT = StdOutLogger.new(1)

class MyTest < Test::Unit::TestCase      
  def test_1()
    assert_equal( 2, 1+1)
    assert_equal( 2, 4/2)

    assert_equal( 1, 3/2)
    assert_equal( 1.5, 3/2.0)
  end
end

但我建议在操作系统级别复制标准输出

ruby mytest.rb > log.txt

这是一个在标准输出和文件输出之间跳过的版本。输出开关只是一个临时解决方案——也许可以做得更好。

class StdOutLogger < IO
  def initialize(*)
    super
    @file = File.open('log.txt', 'w')
    @stdout = true
  end 
  def write(s)
    case s
      when /\AError:/
        @stdout = false #change to file
      when /\A(Pending):/
        @stdout = true #change to file
    end

    if @stdout
    $stdout << s
    else
    @file << s
    end
  end
end
STDOUT = StdOutLogger.new(1)

【讨论】:

  • 这是一种解决方案(也适用于@user899435),问题是它不会在屏幕上留下任何内容。我想将日志文件限制为仅失败和错误,但保留其他所有内容。我还尝试在一批断言之前将 STDOUT 重定向到一个文件,并在断言之后将其切换回旧的 STDOUT,但如果有任何错误或失败,则测试退出并且 STDOUT 永远不会变回。跨度>
  • 我修改了答案以允许同时输出到标准输出和文件。在我的答案的最后是一个版本,我在标准输出和文件之间切换。它在一个例子中起作用,但我敢肯定,它必须适应。我更喜欢将标准输出写入(或复制)到文件并准备后期处理的解决方案。 - 我正在研究另一个想法 - 更多细节将随之而来。
  • 我发布了我的其他解决方案:stackoverflow.com/questions/7098963/… - 似乎是正确的解决方案 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多