如何在 python 单元测试脚本中抑制 ImportWarning

问题描述 投票:0回答:4

我当前正在运行一个单元测试脚本,该脚本成功通过了各种指定的测试,并在控制台中显示了一条烦人的 ImportWarning 消息:

...../lib/python3.6/importlib/_bootstrap.py:219: ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__
  return f(*args, **kwds)
....
----------------------------------------------------------------------
Ran 7 tests in 1.950s

OK

脚本使用以下 main 函数运行:

if __name__ == '__main__':
    unittest.main()

我读过,当像这样调用脚本时可以抑制警告:

python  -W ignore:ImportWarning -m unittest testscript.py

但是,有没有一种方法可以在脚本本身中指定此忽略警告,这样我就不必在每次运行测试脚本时都调用

-W ignore:ImportWarning

提前致谢。

python-3.x python-import python-unittest
4个回答
15
投票

要以编程方式防止出现此类警告,请调整您的代码,以便:

import warnings
if __name__ == '__main__':
    with warnings.catch_warnings():
        warnings.simplefilter('ignore', category=ImportWarning)
        unittest.main()

来源:https://stackoverflow.com/a/40994600/328469

更新:

@billjoie 肯定是正确的。 如果OP选择将answer 52463661作为接受的答案,我对此表示同意。 我可以确认以下内容可以有效地使用 python 版本 2.7.11、3.4.3、3.5.4、3.6.5 和 3.7.1 在运行时抑制此类警告消息:

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import unittest
import warnings


class TestPandasImport(unittest.TestCase):
    def setUp(self):
        warnings.simplefilter('ignore', category=ImportWarning)

    def test_01(self):
        import pandas  # noqa: E402
        self.assertTrue(True)

    def test_02(self):
        import pandas  # noqa: E402
        self.assertFalse(False)


if __name__ == '__main__':
    unittest.main()

但是,我认为OP应该考虑对单元测试的应用程序代码目标进行更深入的调查,并尝试识别导致实际警告的特定包导入或操作,然后尽可能地抑制警告到代码中发生违规的位置。 这将避免在整个单元测试类中抑制警告,这可能会无意中掩盖程序其他部分的警告。

在单元测试之外,应用程序代码中的某个位置:

with warnings.catch_warnings():
    warnings.simplefilter('ignore', category=ImportWarning)
    # import pandas
    # or_ideally_the_application_code_unit_that_imports_pandas()

可能需要一些工作来隔离代码中导致警告的特定位置或利用导致警告的第三方软件,但开发人员将更清楚地了解警告的原因,并且这只会提高程序整体的可维护性。


13
投票

我遇到了同样的问题,并按照 Nels 的描述用

warnings.simplefilter()
语句启动我的单元测试脚本,这对我来说不起作用。根据此来源,这是因为:

[...] 从 Python 3.2 开始,unittest 模块已更新为在运行测试时使用警告模块默认过滤器,并且 [...] 在每次测试之前重置为默认过滤器,这意味着您可能会进行任何更改认为您通过在脚本开头使用 warnings.simplefilter(“ignore”) 来制作整个脚本,在每次测试之间都会被覆盖。

同一来源建议直接或使用优雅的装饰器更新每个测试函数内部的过滤器。一个更简单的解决方案是在 unittest 的

setUp()
方法中定义警告过滤器,该方法在每次测试之前运行。

import unittest
class TestSomething(unittest.TestCase):
    def setUp(self):
        warnings.simplefilter('ignore', category=ImportWarning)
        # Other initialization stuff here

    def test_a(self):
        # Test assertion here.

if __name__ == '__main__':
    unittest.main()

3
投票

带有

def setUp
的解决方案会抑制类中所有方法的警告。如果你不想对所有这些都抑制它,你可以使用装饰器。

来自神经转储

import warnings
def ignore_warnings(test_func):
    def do_test(self, *args, **kwargs):
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            test_func(self, *args, **kwargs)
    return do_test

然后你可以用它来装饰你的测试类中的单个测试方法:

class TestClass(unittest.TestCase):
    @ignore_warnings
    def test_do_something_without_warning()
        self.assertEqual(whatever)

    def test_something_else_with_warning()
        self.assertEqual(whatever)

1
投票

在使用单元测试时,我在 Pycharm 中的一次测试中遇到了相同的警告。当我在测试期间停止尝试导入库时,此警告消失了(我将导入移动到了它应该在的顶部)。我知道该请求是为了抑制,但如果它只发生在选定数量的测试中,这也会使其消失。

© www.soinside.com 2019 - 2024. All rights reserved.