如何修补 Python 的 raise(或 return)关键字以进行单元测试?
How to patch Python's raise (or return) keyword for the purpose of unit testing?
mock.patch 能够捕获的 Python 关键字的命名空间是什么?
当有人想打开补丁或打印时,可以使用mock.patch("builtins.open")
或mock.patch("mymodule.open")
,但这不起作用,例如raise
。
如果我有 raise somemodule.SomeException
语句,那么我可以很容易地测试是否引发了异常,但是我如何断言实际上已经调用了 raise 关键字。喜欢(在 pytest
和 pytest-mock
的帮助下):
def test_myfunction_calls_raise(self, mocker):
mocked = mocker.patch("mymodule.raise")
mymodule.myfunction()
mocked.assert_called_once()
编辑:我有 ,所以 mock.patch 不适用。除此之外,除了明显的解决方案 - 测试结果 - 是否有其他一些有意义的技术来测试代码中是否调用了 Python 关键字(raise
、return
、...)?
编辑 2:
我要测试的实际代码(pynput 的 Listener stop() 在 Xfce 中运行不佳,因此我必须引发异常以停止 Listener 线程):
import pynput
# ...
def stop(self):
"""Stops listener by raising an exception."""
try:
raise pynput.mouse.Listener.StopException
except pynput.mouse.Listener.StopException:
return False
编辑 3:使用以下两种测试方法对上述方法进行了单元测试:
def test_stop_stops_listener(self, mocker):
"""StopException is raised if MagicMock has got StopException attribute."""
mocked = mocker.patch("pynput.mouse.Listener")
with pytest.raises(TypeError): # catching classes that do not inherit from BaseException is not allowed
base.BaseMouse().stop()
assert hasattr(mocked, "StopException")
def test_stop_returns_False(self, mocker):
assert base.BaseMouse().stop() is False
您不能修补关键字。它们是 Python 语法的一部分。当 Python 解释器获取一段 Python 代码时,它会对其进行解析并分几步将其转换为某种内部表示形式 ('bytecode')。然而,字节码与原始源代码不再有直接关系——关键字有 'disappeared'.
相比之下,模块和 class 属性以及它们在代码中的访问仍将在字节码中找到。打补丁基本上就是临时替换这些属性。
或者换句话说,您可以修补属性,但关键字不是属性。
mock.patch 能够捕获的 Python 关键字的命名空间是什么?
当有人想打开补丁或打印时,可以使用mock.patch("builtins.open")
或mock.patch("mymodule.open")
,但这不起作用,例如raise
。
如果我有 raise somemodule.SomeException
语句,那么我可以很容易地测试是否引发了异常,但是我如何断言实际上已经调用了 raise 关键字。喜欢(在 pytest
和 pytest-mock
的帮助下):
def test_myfunction_calls_raise(self, mocker):
mocked = mocker.patch("mymodule.raise")
mymodule.myfunction()
mocked.assert_called_once()
编辑:我有 raise
、return
、...)?
编辑 2: 我要测试的实际代码(pynput 的 Listener stop() 在 Xfce 中运行不佳,因此我必须引发异常以停止 Listener 线程):
import pynput
# ...
def stop(self):
"""Stops listener by raising an exception."""
try:
raise pynput.mouse.Listener.StopException
except pynput.mouse.Listener.StopException:
return False
编辑 3:使用以下两种测试方法对上述方法进行了单元测试:
def test_stop_stops_listener(self, mocker):
"""StopException is raised if MagicMock has got StopException attribute."""
mocked = mocker.patch("pynput.mouse.Listener")
with pytest.raises(TypeError): # catching classes that do not inherit from BaseException is not allowed
base.BaseMouse().stop()
assert hasattr(mocked, "StopException")
def test_stop_returns_False(self, mocker):
assert base.BaseMouse().stop() is False
您不能修补关键字。它们是 Python 语法的一部分。当 Python 解释器获取一段 Python 代码时,它会对其进行解析并分几步将其转换为某种内部表示形式 ('bytecode')。然而,字节码与原始源代码不再有直接关系——关键字有 'disappeared'.
相比之下,模块和 class 属性以及它们在代码中的访问仍将在字节码中找到。打补丁基本上就是临时替换这些属性。
或者换句话说,您可以修补属性,但关键字不是属性。