[英]How to mock / unit test following code in python?
我如何对以下单元进行单元测试?
def sigterm_handler(signum, frame):
pid = os.getpid() # type: int
sys.exit(0)
signal.signal(signal.SIGTERM, sigterm_handler)
我应该嘲笑并确保调用mock吗?
我会写一个测试,在子进程中运行你的代码,可以检查你是否成功终止。
例如,假设您的问题代码位于名为signals.py
的模块中。 您可以编写一个如下所示的测试包装器模块:
test_signals_wrapper.py
from time import sleep
from sys import exit
# import this last to ensure it overrides any prior settings
import signals
while True:
sleep(1)
exit(1) # just in case the loop ends for other reasons
现在你可以编写一个如下所示的单元测试:
test_signals.py
from subprocess import run, TimeoutExpired
from sys import executable
def test_sigterm_handler():
try:
status = run([executable, '-m', 'test_signals_wrapper'], timeout=30)
except TimeoutExpired:
assert False, 'Did not trigger assertion in 30 seconds'
assert status.returncode == 0, f'Wrong return code: {status.returncode}'
这需要为您的测试提供一些额外的基础架构,但它解决了测试此代码时的所有问题。 通过在子sys.exit
运行,您可以自由执行sys.exit
并获取返回值。 通过使用包装器脚本,您可以控制代码的加载和运行方式。 您不需要模拟任何东西,只需确保您的软件包设置正确,并且您的测试运行器不会尝试将包装器脚本作为测试。
猴子修补处理程序并在测试时发送信号?
import os
import signal
import sys
import time
# your handler
def sigterm_handler(signum, frame):
print("Handled")
pid = os.getpid() # type: int FIXME: what's this for?
sys.exit(0)
signal.signal(signal.SIGTERM, sigterm_handler)
# Mock out the existing sigterm_handler
_handled = False
def mocked_sigterm_handler(signum, frame):
print("Mocked")
_handled = True
# register the handler
signal.signal(signal.SIGTERM, mocked_sigterm_handler)
# test sending the signal
os.kill(os.getpid(), signal.SIGTERM)
print(f"done ({_handled})")
# reset your handler?
signal.signal(signal.SIGTERM, sigterm_handler)
如果你想测试你自己的处理程序,你可能不得不把这样的代码放在这个不太漂亮的处理程序中。
if _unittesting_sigterm_handler:
_handled = True
else:
sys.exit(0)
然后你可以直接调用处理程序(或在调用中传递测试标志)。
_unittesting_sigterm_handler = True
sigterm_handler(0, None)
您显示的代码行不适合进行单元测试,但应该进行集成测试。 原因是,您的代码行仅包含与其他组件的交互(在本例中为signal
, sys
和os
模块)。
因此,您可能遇到的错误在于与这些其他组件的交互:您是否使用正确顺序的参数的正确值调用正确的组件中的正确函数,并且是您期望它们的结果/反应是?
所有这些问题都无法在单元测试中得到解答,在单元测试中可以找到可以在隔离单元中找到的错误:如果你模拟signal
, sys
和/或os
依赖关系,那么你将编写你的模拟,以便它们反映您对这些组件的(可能是错误的)理解。 因此,单元测试将成功,尽管集成系统中的代码可能会失败。 如果您的意图是代码在不同的系统上运行,您甚至可能会遇到代码在一个集成(可能是Linux)中工作但在另一个集成中失败的情况(可能是Windows)。
因此,对于像您这样的代码,单元测试和单元测试的模拟没有多大价值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.