如何在 python 单元测试脚本中抑制 ImportWarning
How to suppress ImportWarning in a python unittest script
我目前正在 运行ning 一个单元测试脚本,它成功地通过了各种指定的测试,并在控制台中显示了一个烦人的 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
脚本 运行 具有以下主要功能:
if __name__ == '__main__':
unittest.main()
我读到当这样调用脚本时可以抑制警告:
python -W ignore:ImportWarning -m unittest testscript.py
但是,有没有一种方法可以在脚本本身中指定此忽略警告,这样我就不必在每次测试脚本为 运行 时都调用 -W ignore:ImportWarning
?
提前致谢。
要以编程方式防止出现此类警告,请调整您的代码以便:
import warnings
if __name__ == '__main__':
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=ImportWarning)
unittest.main()
来源:
更新:
@billjoie 肯定是正确的。如果 OP 选择 作为接受的答案,我同意。我可以确认以下内容在 运行 时使用 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 应该考虑对单元测试的应用程序代码目标进行更深入的调查,并尝试确定导致实际警告的特定包导入或操作,然后抑制警告尽可能靠近代码中发生违规的位置。这将避免在整个单元测试中抑制警告 class,这可能会无意中掩盖程序其他部分的警告。
在单元测试之外,应用程序代码中的某处:
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=ImportWarning)
# import pandas
# or_ideally_the_application_code_unit_that_imports_pandas()
隔离代码中导致警告或利用第三方软件导致警告的特定位置可能需要一些工作,但开发人员将更清楚地了解导致警告的原因警告,这只会提高程序的整体可维护性。
我遇到了同样的问题,按照 Nels 的描述,用 warnings.simplefilter()
语句启动我的单元测试脚本,但这对我不起作用。根据this source,这是因为:
[...] as of Python 3.2, the unittest module was updated to use the warnings module default filter when running tests, and [...] resets to the default filter before each test, meaning that any change you may think you are making scriptwide by using warnings.simplefilter(“ignore”) at the beginning of your script gets overridden in between every test.
同一来源建议直接或使用优雅的装饰器更新每个测试函数内部的过滤器。一个更简单的解决方案是在 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()
我在 Pycharm 中对使用 unittest 的一项测试发出了相同的警告。当我在测试期间停止尝试导入库时,此警告消失了(我将导入移到了它应该在的顶部)。我知道请求是为了抑制,但如果它只在 select 次测试中发生,这也会使它消失。
带有 def setUp
的解决方案抑制 class 中所有方法的警告。如果你不想对所有这些都进行抑制,你可以使用装饰器。
来自Neural Dump:
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:
class TestClass(unittest.TestCase):
@ignore_warnings
def test_do_something_without_warning()
self.assertEqual(whatever)
def test_something_else_with_warning()
self.assertEqual(whatever)
我目前正在 运行ning 一个单元测试脚本,它成功地通过了各种指定的测试,并在控制台中显示了一个烦人的 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
脚本 运行 具有以下主要功能:
if __name__ == '__main__':
unittest.main()
我读到当这样调用脚本时可以抑制警告:
python -W ignore:ImportWarning -m unittest testscript.py
但是,有没有一种方法可以在脚本本身中指定此忽略警告,这样我就不必在每次测试脚本为 运行 时都调用 -W ignore:ImportWarning
?
提前致谢。
要以编程方式防止出现此类警告,请调整您的代码以便:
import warnings
if __name__ == '__main__':
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=ImportWarning)
unittest.main()
来源:
更新:
@billjoie 肯定是正确的。如果 OP 选择
#! /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 应该考虑对单元测试的应用程序代码目标进行更深入的调查,并尝试确定导致实际警告的特定包导入或操作,然后抑制警告尽可能靠近代码中发生违规的位置。这将避免在整个单元测试中抑制警告 class,这可能会无意中掩盖程序其他部分的警告。
在单元测试之外,应用程序代码中的某处:
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=ImportWarning)
# import pandas
# or_ideally_the_application_code_unit_that_imports_pandas()
隔离代码中导致警告或利用第三方软件导致警告的特定位置可能需要一些工作,但开发人员将更清楚地了解导致警告的原因警告,这只会提高程序的整体可维护性。
我遇到了同样的问题,按照 Nels 的描述,用 warnings.simplefilter()
语句启动我的单元测试脚本,但这对我不起作用。根据this source,这是因为:
[...] as of Python 3.2, the unittest module was updated to use the warnings module default filter when running tests, and [...] resets to the default filter before each test, meaning that any change you may think you are making scriptwide by using warnings.simplefilter(“ignore”) at the beginning of your script gets overridden in between every test.
同一来源建议直接或使用优雅的装饰器更新每个测试函数内部的过滤器。一个更简单的解决方案是在 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()
我在 Pycharm 中对使用 unittest 的一项测试发出了相同的警告。当我在测试期间停止尝试导入库时,此警告消失了(我将导入移到了它应该在的顶部)。我知道请求是为了抑制,但如果它只在 select 次测试中发生,这也会使它消失。
带有 def setUp
的解决方案抑制 class 中所有方法的警告。如果你不想对所有这些都进行抑制,你可以使用装饰器。
来自Neural Dump:
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:
class TestClass(unittest.TestCase):
@ignore_warnings
def test_do_something_without_warning()
self.assertEqual(whatever)
def test_something_else_with_warning()
self.assertEqual(whatever)