unittest blacklist namespace 并且任何引用它的尝试都失败
unittest blacklist namespace and fail any attempt to reference it
在对包装器库进行单元测试的情况下,在没有 depending/exercising 上游库的情况下测试包装器是一个目标;在一个已知的案例中,所有对上游库的调用都可以被模拟,这就是我所做的,但我对包装器的更改感到沮丧,这些更改引入了对上游库的更多调用被模拟工具错过;
我怎样才能最好地让任何尝试使用给定名称空间的测试失败?
我目前的想法是改变所有的单元测试方法来拥有像
这样的猴子补丁
@unittest.mock.patch('wrapper_namespace.upsteam_namespace')
并用一个可以断言不受影响的模拟回复上游库;我希望有一个全球通用的选项,这样我
- 不必为每个测试方法都添加一个 monkeypatch,尽管这种粒度级别是可以接受的;但也不必执行模拟从未在测试方法中使用过的断言(或者让装饰器来完成所有这些)
- 禁止从软件的任何部分访问上游库
(例如,Wrapper 调用 B 调用 Upstream,B 对上游的调用可能不会被捕获)
您不必为每个测试方法都打补丁。如果您正在使用 unittest
,您可以轻松地修补 class
,或者只需将模块分配给您想要修补它的任何内容。这是一个可行的例子:
some_lib.py 中的假库:
def some_lib_func():
raise ValueError("I've been called.")
def some_other_lib_func():
raise ValueError("I've been called.")
class SomeClass:
def __init__(self):
raise ValueError("I've been constructed.")
wrapper.py:
import some_lib
def wrapper1():
some_lib.some_lib_func()
def wrapper2():
some_lib.some_other_lib_func()
def wrapper3():
x = some_lib.SomeClass()
test.py:
from unittest.mock import patch, MagicMock
import unittest
import wrapper
# Alternative:
# wrapper.some_lib = MagicMock()
# Can patch an entire class
@patch('wrapper.some_lib', MagicMock())
class TestWrapper(unittest.TestCase):
def test_wrapper1(self):
wrapper.wrapper1()
def test_wrapper2(self):
wrapper.wrapper2()
def test_wrapper3(self):
wrapper.wrapper3()
if __name__ == "__main__":
unittest.main()
如果 some_lib
中的 functions/classes 被调用,我们会爆炸,但它们不是:
Matthews-MacBook-Pro:Whosebug matt$ python test.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s
OK
欢迎在 wrapper.some_lib = MagicMock()
中评论补丁和评论。在这个玩具示例中,您会得到相同的结果,但两种方法之间存在重大差异:
使用@patch('wrapper.some_lib', MagicMock())
补丁仅适用于该测试用例class.
但是,当使用 wrapper.some_lib = MagicMock()
时,该补丁将在 整个 python 程序,除非您保存原始模块并在某个时候手动修补它。使用 wrapper
模块的所有内容都将获得模拟版本。
所以你可以这样:
original_lib = wrapper.some_lib
wrapper.some_lib = MagicMock()
...
# call some test suite, every call to the wrapper module will be mocked out
...
wrapper.some_lib = original_lib
...
# call some other test suite that actually needs the real thing
...
HTH.
编辑: 稍微误读了您的问题,但您可以检查 MagicMock
对象以查看它们是否已被调用,如果已调用,则测试失败。或者只是用调用时失败的东西来修补(而不是 MagicMock
)。如果需要,我可以提供代码来执行此操作(只需发表评论),但希望以上内容可以帮助您入门。我认为问题的症结在于全局补丁。干杯!
在对包装器库进行单元测试的情况下,在没有 depending/exercising 上游库的情况下测试包装器是一个目标;在一个已知的案例中,所有对上游库的调用都可以被模拟,这就是我所做的,但我对包装器的更改感到沮丧,这些更改引入了对上游库的更多调用被模拟工具错过;
我怎样才能最好地让任何尝试使用给定名称空间的测试失败?
我目前的想法是改变所有的单元测试方法来拥有像
这样的猴子补丁@unittest.mock.patch('wrapper_namespace.upsteam_namespace')
并用一个可以断言不受影响的模拟回复上游库;我希望有一个全球通用的选项,这样我
- 不必为每个测试方法都添加一个 monkeypatch,尽管这种粒度级别是可以接受的;但也不必执行模拟从未在测试方法中使用过的断言(或者让装饰器来完成所有这些)
- 禁止从软件的任何部分访问上游库 (例如,Wrapper 调用 B 调用 Upstream,B 对上游的调用可能不会被捕获)
您不必为每个测试方法都打补丁。如果您正在使用 unittest
,您可以轻松地修补 class
,或者只需将模块分配给您想要修补它的任何内容。这是一个可行的例子:
some_lib.py 中的假库:
def some_lib_func():
raise ValueError("I've been called.")
def some_other_lib_func():
raise ValueError("I've been called.")
class SomeClass:
def __init__(self):
raise ValueError("I've been constructed.")
wrapper.py:
import some_lib
def wrapper1():
some_lib.some_lib_func()
def wrapper2():
some_lib.some_other_lib_func()
def wrapper3():
x = some_lib.SomeClass()
test.py:
from unittest.mock import patch, MagicMock
import unittest
import wrapper
# Alternative:
# wrapper.some_lib = MagicMock()
# Can patch an entire class
@patch('wrapper.some_lib', MagicMock())
class TestWrapper(unittest.TestCase):
def test_wrapper1(self):
wrapper.wrapper1()
def test_wrapper2(self):
wrapper.wrapper2()
def test_wrapper3(self):
wrapper.wrapper3()
if __name__ == "__main__":
unittest.main()
如果 some_lib
中的 functions/classes 被调用,我们会爆炸,但它们不是:
Matthews-MacBook-Pro:Whosebug matt$ python test.py
...
----------------------------------------------------------------------
Ran 3 tests in 0.001s
OK
欢迎在 wrapper.some_lib = MagicMock()
中评论补丁和评论。在这个玩具示例中,您会得到相同的结果,但两种方法之间存在重大差异:
使用@patch('wrapper.some_lib', MagicMock())
补丁仅适用于该测试用例class.
但是,当使用 wrapper.some_lib = MagicMock()
时,该补丁将在 整个 python 程序,除非您保存原始模块并在某个时候手动修补它。使用 wrapper
模块的所有内容都将获得模拟版本。
所以你可以这样:
original_lib = wrapper.some_lib
wrapper.some_lib = MagicMock()
...
# call some test suite, every call to the wrapper module will be mocked out
...
wrapper.some_lib = original_lib
...
# call some other test suite that actually needs the real thing
...
HTH.
编辑: 稍微误读了您的问题,但您可以检查 MagicMock
对象以查看它们是否已被调用,如果已调用,则测试失败。或者只是用调用时失败的东西来修补(而不是 MagicMock
)。如果需要,我可以提供代码来执行此操作(只需发表评论),但希望以上内容可以帮助您入门。我认为问题的症结在于全局补丁。干杯!