python - 如何使用pytest模拟完全重启
问题描述
如何测试我的程序对意外关闭的鲁棒性?
我的 python 代码将在一个意外关闭的微控制器上运行。我想测试代码的每个部分意外重启并验证它是否正确处理。
尝试:我尝试将代码放入它自己的进程中,然后提前终止它,但这不起作用,因为 MyClass 从命令行调用 7zip ,即使在进程终止后仍会继续:
import multiprocessing
import os
def MyClass(multiprocessing.Process):
...
def run():
os.system("7z a myfile.7z myfile")
process = MyClass()
process.start()
time.sleep(4)
print("terminating early")
process.terminate()
print("done")
我想要的是:
class TestMyClass(unittest.TestCase):
def test_MyClass_continuity(self):
myclass = MyClass().start()
myclass.kill_everything()
myclass = MyClass().start()
self.assert_everything_worked_as_expected()
是否有捷径可寻?如果不是,你如何设计可以在任何时候终止的健壮代码(例如测试状态机)?
类似问题(截至 21 年 10 月 26 日未回答):模拟 pytest 中的异常终止
非常感谢!
解决方案
您的逻辑启动一个包含在对象中的进程,该MyClass
对象本身通过os.system
调用产生一个新进程。
当你终止MyClass
进程时,你杀死了父进程,但你让7zip
进程作为孤儿运行。
此外,该方法向子进程process.terminate
发送信号。SIGTERM
子进程可以拦截所述信号并在终止之前执行一些清理例程。如果您想模拟没有机会清理的情况(断电),这并不理想。您很可能想要发送SIGKILL
信号(在 Linux 上)。
要杀死父子进程,需要处理整个进程组。
import os
import time
import signal
import multiprocessing
class MyClass(multiprocessing.Process):
def run(self):
# Ping localhost for a limited amount of time
os.system("ping -c 12 127.0.0.1")
process = MyClass()
process.start()
time.sleep(4)
print("terminating early")
# Send SIGKILL signal to the entire process group
group_id = os.getpgid(process.pid)
os.killpg(group_id, signal.SIGKILL)
print("done")
以上仅适用于 Unix 操作系统,不适用于 Windows 操作系统。
对于 Windows,您需要使用psutil模块。
import os
import time
import multiprocessing
import psutil
class MyClass(multiprocessing.Process):
def run(self):
# Ping localhost for a limited amount of time
os.system("ping -c 12 127.0.0.1")
def kill_process_group(pid):
process = psutil.Process(pid)
children = process.children(recursive=True)
# First terminate all children
for child in children:
child.kill()
psutil.wait_procs(children)
# Then terminate the parent process
process.kill()
process.wait()
process = MyClass()
process.start()
time.sleep(4)
print("terminating early")
kill_process_group(process.pid)
print("done")
推荐阅读
- github - 通过 ssh 登录另一台机器(不提供密码)时,如何与 github 正常交互?
- ios - 在客户端关闭 wifi 时 socket.io 重新连接(从 wifi 切换到 LTE 并再次返回)
- c++ - Python“模板”等价物
- c - Windows:基本 HTTPS 客户端(不工作以及相关问题)
- android - 如何绘制用分隔线绘制的圆形边框笔划?
- ios - iOS 强制热节流
- python - 如何将我的输出重新排列为单个对象并用逗号分隔?MongoDB/蟒蛇
- sql-server - 使用 SQL Server,我试图将变量值插入批量插入命令但没有成功
- conda - Conda 相当于 pip 安装可选的额外组件是什么?
- pandas - 删除在熊猫数据框中移动的两列重复值的行?