如何在PyTest中测试KeyboardInterrupt语句?



假设我的主文件中有这样一个函数:

# main.py
import time
def little_sleep(num):
time.sleep(float(f'0.{i}'))
def wait():
i = 0
while True:
try:
little_sleep(i)
except KeyboardInterrupt:
print("Uh Oh!! You really got me there, I guess I'll just have to exit then...")
break
return

我必须PyTest这个模块和其中的每个函数。我的问题是,我将如何使用KeyboardInterrupt进行测试,而不会对其他测试发生任何事情,并且内部功能不会受到影响?

# test_main.py
import main
from multiprocessing import Process
import os, time, signal
def test_wait(capfd):
process = Process(target= main.wait)
process.start()
time.sleep(1)

# I tried this but it is sometimes killing the little_sleep() function 
# and hence the signal is not getting captured by the except 
os.kill(process.pid, signal.CTRL_C_EVENT)
# I also tried this but it is directly killing the process without any output and hence is not feasible
process.kill()
captured = capfd.readouterr()
assert captured.out == "Uh Oh!! You really got me there, I guess I'll just have to exit then...n"
>> pytest test_main.py
collected 1 item
test_main.py F 
=============================== FAILURES ===================================
_______________________________ test_wait __________________________________
capfd = <_pytest.capture.CaptureFixture object at 0x000001F89F7BD400>
def test_wait(capfd):
...
captured = capfd.readouterr()
>       assert captured.out == "Uh Oh!! You really got me there, I guess I'll just have to exit then...n"
E       AssertionError: assert '' == 'Uh Oh!! You ...xit then...n'
E         - Uh Oh!! You really got me there, I guess I'll just have to exit then...
test_main.py:19: AssertionError

有什么解决办法吗??

您可以使用MagicMock及其side_effect属性来模拟little_sleep,从而引发KeyboardInterrupt异常:

import unittest.mock
import main
def test_wait(capfd):
unittest.mock.MagicMock('main.little_sleep', side_effect=KeyboardInterrupt)
main.wait()
captured = capfd.readouterr()
assert captured.out == "Uh Oh!! You really got me there, I guess I'll just have to exit then...n"

(未测试)

您可以自己安装信号处理程序并管理KeyboardInterrupt

import signal
# Save the default handler and optionally restore it at the end of the test.
default_handler = signal.getsignal(signal.SIGINT)
def handler(signum, frame):
print('Signal handler called with signal', signum)

signal.signal(signal.SIGINT, handler)

见https://docs.python.org/3/library/signal.html

此外,我会把更大的范围的尝试…除了使它更健壮和高效:

try:
while True:
little_sleep(i)
except KeyboardInterrupt:
print("Uh Oh!! You really got me there, I guess I'll just have to exit then...")

它可以不处理信号就解决你的问题。

相关内容

  • 没有找到相关文章

最新更新