我的代码很简单:
def start():
signal(SIGINT, lambda signal, frame: raise SystemExit())
startTCPServer()
所以我用SIGINT
的信号处理注册我的应用程序,然后我开始启动一个TCP监听器。
这是我的问题:
如何使用python代码发送SIGINT信号?
如何测试应用程序是否收到SIGINT信号,是否会引发SystemExit异常?
如果我在测试中运行start()
,它会阻止,我该如何向其发送信号?
答案 0 :(得分:4)
首先,测试信号本身是功能或集成测试,而不是单元测试。见What's the difference between unit, functional, acceptance, and integration tests?
您可以使用subprocess.Popen()
将Python脚本作为子进程运行,然后使用Popen.send_signal()
method向该进程发送信号,然后使用Popen.poll()
测试该进程已退出。
答案 1 :(得分:1)
- 如何使用python代码发送SIGINT信号?
醇>
您可以使用os.kill
,这有点误导,可用于通过其ID向任何进程发送任何信号。可以通过os.getpid()
找到应用程序/测试的进程ID,因此您可以...
pid = os.getpid()
# ... other code discussed later in the answer ...
os.kill(pid, SIGINT)
- 如何测试应用程序是否收到SIGINT信号,是否会引发SystemExit异常?
醇>
测试中常用的方法是检查某些代码是否引发SystemExit,是unittest.TestCase::assertRaises
...
import start
class TestStart(unittest.TestCase):
def test_signal_handling(self):
# ... other code discussed later in the answer ...
with self.assertRaises(SystemExit):
start.start()
- 如果我在测试中运行start(),它会阻止,我该如何向它发送信号?
醇>
这是诀窍:你可以启动另一个线程然后将信号发送回阻塞的主线程。
将所有内容放在一起,假设您的生产start
功能位于start.py
:
from signal import (
SIGINT,
signal,
)
import socketserver
def startTCPServer():
# Taken from https://docs.python.org/3.4/library/socketserver.html#socketserver-tcpserver-example
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024).strip()
self.request.sendall(self.data.upper())
HOST, PORT = "localhost", 9999
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
server.serve_forever()
def start():
def raiseSystemExit(_, __):
raise SystemExit
signal(SIGINT, raiseSystemExit)
startTCPServer()
然后您的测试代码可能如下所示,例如test.py
import os
from signal import (
SIGINT,
)
import threading
import time
import unittest
import start
class TestStart(unittest.TestCase):
def test_signal_handling(self):
pid = os.getpid()
def trigger_signal():
# You could do something more robust, e.g. wait until port is listening
time.sleep(1)
os.kill(pid, SIGINT)
thread = threading.Thread(target=trigger_signal)
thread.daemon = True
thread.start()
with self.assertRaises(SystemExit):
start.start()
if __name__ == '__main__':
unittest.main()
并使用
运行python test.py
中的答案相同