Python:如何测试使用 fork 的程序?

问题描述 投票:0回答:2

我正在编写一个程序,该程序在生产中使用相同代码的多个实例。然后实例通过网络进行通信,但这与这里无关。

在开发过程中,我多次fork初始进程以获得完整的实例设置,非常方便。

但是,尝试对此编写集成测试给我带来了问题:测试框架(unittest/nosetests/py.test)当然也是分叉的,因此我最终得到了多个测试框架副本,提供乱码结果作为每个测试框架的输出孩子的单元测试重叠。

一个简化的例子:

  • 程序是聊天客户端,通过某种网络连接连接到另一个客户端(例如,redis pubsub)
  • 程序公开 API 来发布和读取消息
  • 我想分叉两个相互连接的程序实例
  • 测试应使用 API 来确保客户端通过相互发送/接收消息来工作
  • 主进程监督子进程的错误并运行测试套件

为了实现这一点,我需要从子进程中“卸载”或停止测试框架。我该怎么做?

我可以通过仅在分叉子项后调用测试套件来解决此问题,但我需要为每个测试重新启动所有子项。

python testing pytest python-unittest nose
2个回答
0
投票

在这种情况下分叉进程是一个很大的麻烦,因为子进程继承父进程的完整堆栈,包括测试框架的运行实例。

解决这个问题基本上有两种选择:

第一是在初始化测试框架之前进行分叉,然后从测试中访问子进程。如果子进程寿命很长,那么这很有效,但如果每次测试都启动子进程,甚至可能使用不同的测试装置/场景,那么这会很麻烦。

第二点是通过简单地使用

subprocess
/
Popen
启动进程来放弃所有分叉。我找到了一个名为 xprocess 的 pytest 插件,它可以帮助您完成此任务。它没有提供我所需要的东西,但它为我指明了正确的方向。


0
投票

向 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')
© www.soinside.com 2019 - 2024. All rights reserved.