我正在编写一个程序,该程序在生产中使用相同代码的多个实例。然后实例通过网络进行通信,但这与这里无关。
在开发过程中,我多次fork初始进程以获得完整的实例设置,非常方便。
但是,尝试对此编写集成测试给我带来了问题:测试框架(unittest/nosetests/py.test)当然也是分叉的,因此我最终得到了多个测试框架副本,提供乱码结果作为每个测试框架的输出孩子的单元测试重叠。
一个简化的例子:
为了实现这一点,我需要从子进程中“卸载”或停止测试框架。我该怎么做?
我可以通过仅在分叉子项后调用测试套件来解决此问题,但我需要为每个测试重新启动所有子项。
在这种情况下分叉进程是一个很大的麻烦,因为子进程继承父进程的完整堆栈,包括测试框架的运行实例。
解决这个问题基本上有两种选择:
第一是在初始化测试框架之前进行分叉,然后从测试中访问子进程。如果子进程寿命很长,那么这很有效,但如果每次测试都启动子进程,甚至可能使用不同的测试装置/场景,那么这会很麻烦。
第二点是通过简单地使用
subprocess
/ Popen
启动进程来放弃所有分叉。我找到了一个名为 xprocess 的 pytest 插件,它可以帮助您完成此任务。它没有提供我所需要的东西,但它为我指明了正确的方向。
向 arnuschky 提供的解决方案添加一些内容。
在使用分叉的代码相当有限的情况下,我发现在初始化期间存储测试套件的 PID(例如,在
setUp
中),然后与相关位置的 PID 进行比较(例如,在 tearDown
中)
)也可以解决问题。
为了说明这个想法:
class Test(TestCase):
def setUp(self):
self.testsuite_pid = os.getpid()
self.tempdir = tempfile.mkdtemp()
def tearDown(self):
if self.testsuite_pid == os.getpid():
shutil.rmtree(self.tempdir)
def test(self):
try:
ret = run_tested_code()
except:
if self.testsuite_pid == os.getpid():
raise
if self.testsuite_pid != os.getpid():
self.assertEqual(ret, 'expected ret')