【问题标题】:How to overwrite the nosetest teardown function?如何覆盖nosetest拆解功能?
【发布时间】:2018-01-03 08:53:23
【问题描述】:

使用nosetest 进行测试时,每个测试用例的结果可以是“成功”、“失败”或“错误”。这将作为“.”、“F”和“E”写入 STDOUT。

  • .
  • F
  • E

有没有办法覆盖这个函数并打印出额外的调试信息?

附录

根据下面给出的信息,我创建了以下测试代码:

from nose.tools import assert_true
from nose.plugins import Plugin

class Tester(Plugin):

    def addSuccess(self, test):
        print("Test successful")

    def addError(self, test, err):
        print("Had error: %s" % err)

    def addFailure(self, test, err):
        print("Had failure: %s" % err)


class TestSuite(object):
    def test1(self):
        assert_true(True)

但是,当我使用

运行此示例测试时,不会生成额外的输出
nosetests --nologcapture -s test1.py 

我需要以某种方式“注册”那个插件吗?

附录2:

我创建了一个文件plugin1.py,内容如下:

import os
from nose.plugins import Plugin

class Plugin1(Plugin):
    def addSuccess(self, test):
        print("Test successful")

    def addError(self, test, err):
        print("Had error: %s" % err)

    def addFailure(self, test, err):
        print("Had failure: %s" % err)

    def options(self, parser, env=os.environ):
        super(Plugin1, self).options(parser, env=env)

    def configure(self, options, conf):
        super(Plugin1, self).configure(options, conf)

和测试脚本如下(test1.py):

from nose.tools import assert_true


class TestSuite(object):
    def test1(self):
        assert_true(True)


import nose
from plugin1 import Plugin1

if __name__ == '__main__':
    nose.main(addplugins=[Plugin1()])

但我仍然得到相同的结果。我想我必须以其他方式“注册”插件。但是怎么做?在这一点上documentation 几乎不存在...

运行整个测试

python test1.py

产生相同的输出,但不是plugin1.py 中给出的额外文本输出。

【问题讨论】:

  • 您在寻找哪些额外信息?对于失败的测试鼻子也会显示堆栈跟踪

标签: python unit-testing nose


【解决方案1】:

您可以使用nose plug-in framework 执行此操作。基本上你的插件需要提供一个addError 方法,当测试出错时会调用它。该方法获取传入的测试用例,您应该能够反省哪里出了问题并在那里记录额外的调试信息。看看TestTextResultResultProxy 类。

示例包含一个完整的插件,可将输出流 (HTMLPlugin) 修改为 html 格式。


更新

文档确实很糟糕。这是我拼凑的。

import sys
from nose.tools import assert_true
import nose
from nose.plugins import Plugin

class Plugin1(Plugin):
    def __init__(self):
        self.reports = []
        # self.name = 'mega-plugin'
        super(Plugin1, self).__init__()

    def addSuccess(self, test):
        print('Test successful')
        self.reports.append("Test successful")
        self.stream.writeln("Test successful")

    def setOutputStream(self, stream):
        self.stream = stream
        return None

    def finalize(self, result):
        for t in self.reports:
            self.stream.writeln('finalize - ' + t)

class TestSuite(object):
    def test1(self):
        assert_true(True)


if __name__ == '__main__':
    nose.main(argv=sys.argv + ['--with-plugin1'], addplugins=[Plugin1()])

输出是

Test successful
.
----------------------------------------------------------------------
Ran 1 test in 0.003s

OK
finalize - Test successful

几个观察:

  1. 仅使用addplugins 注册它不启用它的插件
  2. 您必须指定--with-PLUGIN-NAME 才能实际使用它
  3. --with-PLUGIN-NAME 不能在 argv 中排在第一位,因为这通常是程序名称
  4. 插件从类名和自动--with-PLUGIN-NAME标志中获取一个自动名称,您可以覆盖名称,因此也可以覆盖--with-SOMETHING标志。
  5. 如果您想在测试运行时打印到stderr,您还必须指定--nocapture,否则nose 将阻塞标准输出(注意来自addSuccessprint 不会显示在输出中)
  6. 您应该实现setOutputStream 方法并存储对输出流的本地引用,或者可能在__init__ 期间设置您自己的输出流。
  7. 如果你有一个setOutputStream 方法并且从中返回 None,其他插件可以使用相同的流。您可以返回一个虚拟流来抑制默认输出 (https://nose.readthedocs.io/en/latest/plugins/writing.html#recipes)
  8. 为了保持一切整洁,您还应该实现finalize 方法并仅在此处打印输出,而不是在测试运行时打印输出 - 在测试期间调用addSuccesaddFailure 等,@987654347在所有测试完成后调用 @。

所有这些都应该在文档中。

【讨论】:

  • 感谢您的提示,但如何让它发挥作用?我在测试脚本中创建了一个 Plugins 类,但输出没有改变。这样的插件怎么用?
  • 您可以使用argv=sys.argv + ['--with-plugin1'],这样仍然可以在命令行中传递命令行参数
  • @MattiLyra:感谢您提供的明确示例,但它对我不起作用。我尝试使用nosetest -s test1.pynosetests test1.py 以及python test1.py 运行脚本。我仍然得到原始未更改的输出。
  • 看起来'main'部分根本没有执行(使用nosetests时)
  • 我以python test1.py 运行它,它确实有效。我正在使用nose-1.3.7python-3.5.2 - 调用nosetest 将不起作用,因为这将跳过您已经发现的.main 跑步者。你能打开--nocapture 并插入一些print 语句来查看是否调用了任何东西吗?
猜你喜欢
  • 1970-01-01
  • 2017-11-17
  • 1970-01-01
  • 2015-12-27
  • 1970-01-01
  • 1970-01-01
  • 2016-10-20
  • 2011-10-31
  • 1970-01-01
相关资源
最近更新 更多