假设我的主文件中有这样一个函数:
# 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...")
它可以不处理信号就解决你的问题。