【问题标题】:How to suppress ResourceWarning()s in doctest running under unittest如何在 unittest 下运行的 doctest 中抑制 ResourceWarning()s
【发布时间】:2021-07-28 20:17:21
【问题描述】:

我的 Python doctests 打开一些它永远不会关闭的文件。这不会引起任何问题;当对象被销毁时它们会自动关闭,并且添加逻辑以确保它们被明确关闭会不必要地使我的文档复杂化。

但是,当 doctest 在 unittest 内部运行时,它们开始发出 ResourceWarning()s,给我的输出添加无用的噪音。

例如,给定leak.py:

def hello(f):
    """ 
    >>> a = open("test-file","w")
    >>> hello(a)
    >>> open("test-file").read()
    'hello'
    """
    f.write("hello")
    f.flush()

def load_tests(loader, tests, ignore):
    import doctest
    tests.addTests(doctest.DocTestSuite())
    return tests

使用 Python 3.6.9 在 doctest 和 unittest 下运行它会生成:

$ python3 --version
Python 3.6.9
$ python3 -m doctest leak.py -v
[...] 
3 passed and 0 failed.
Test passed.
$ python3 -m unittest leak
/tmp/fileleak/leak.py:1: ResourceWarning: unclosed file <_io.TextIOWrapper name='test-file' mode='r' encoding='UTF-8'>
  def hello(f):
/usr/lib/python3.6/doctest.py:2175: ResourceWarning: unclosed file <_io.TextIOWrapper name='test-file' mode='w' encoding='UTF-8'>
  test.globs.clear()
.
----------------------------------------------------------------------
Ran 1 test in 0.003s

OK

有几种方法可以在 doctest 中清理它,但它们都会增加复杂性,从而分散文档的注意力。这包括对a.close() 的显式调用,使用with open("test-file") as a:(它还将测试的输出推送到with 块下方,或者使用`warnings.simplefilter("ignore") 彻底丢弃警告。

如何让 doctest 在 unittest 下运行以抑制 ResourceWarning()s 像 doctest 一样?

【问题讨论】:

    标签: python python-unittest suppress-warnings doctest


    【解决方案1】:

    doctest没有禁止这些警告。 unittest 是 启用它们。我们可能想要 unittest 让他们为我们的更多 传统的单元测试,所以我们不想在全局范围内压制这些。

    我已经在使用load_tests 将文档测试添加到unittest,所以我们有 放置它的好地方。我们不能直接拨打warnings.filterwarnings()load_tests 中,因为过滤器在我们的测试运行之前被重置。我们可以使用 setUp 参数为 doctest.DocTestSuite 提供一个函数来为我们完成这项工作。

    def load_tests(loader, tests, ignore):
        import doctest
        import warnings
        def setup(doc_test_obj):
            for module in (__name__, 'doctest'):
                warnings.filterwarnings("ignore",
                        message= r'unclosed file <_io.TextIOWrapper',
                        category=ResourceWarning,
                        module=module+"$")
        tests.addTests(doctest.DocTestSuite(setUp=setup))
        return tests
    

    在我们创建的对象可能被破坏的任何地方,我们都需要过滤器 一个ResourceWarning 生成。这包括我们自己的模块 (__name__),但它 还包括doctest,因为一些全局变量直到 DocTestCase.tearDown.

    通过仔细指定按类别、消息和模块过滤的内容,这 应该限制​​抑制设计警告的风险,但它并非没有风险。

    【讨论】:

      猜你喜欢
      • 2018-12-05
      • 2020-06-25
      • 2021-12-20
      • 2018-12-06
      • 2020-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-06
      相关资源
      最近更新 更多