【问题标题】:How to subprocess a pymodbus tcp server in a python unit test and terminate it after all the tests have been executed?如何在 python 单元测试中子处理 pymodbus tcp 服务器并在执行所有测试后终止它?
【发布时间】:2021-01-13 22:05:50
【问题描述】:

在介绍我面临的问题之前,我将尝试为您提供一些背景信息。 我有一个名为 Actuator 的组件,它依赖于模块 pymodbus。当我测试这个组件时,我使用基于 pymodbus 的 modbus TCP 服务器以最简单的方式进行了测试。基本上,我将服务器作为 python 脚本(正是这个:https://pymodbus.readthedocs.io/en/latest/source/example/synchronous_server.html)在一个新的 shell 中运行,我的应用程序(包括执行器)在另一个 shell 中运行。一切都像魅力一样。

我现在想做的是为执行器编写一个单元测试,使用 python unittest 和 pymodbus 并尝试自动化我之前所做的事情。我的想法是在 setUp 方法中将 modbus 服务器作为子进程运行(考虑到我不需要服务器的输出),在我的测试套件中使用它,然后在 tearDown 方法中终止它,如下所示:

class TestActuator(unittest.TestCase):
    """Class to test the actuator module"""

    def setUp(self):
        """
        Setup a real Actuator object with a modbus server running
        in background for tests
        """
        modbus_server_path = "path/to/modbus_server.py"
        cmd = "python3 {}".format(modbus_server_path)
        self.modbus_server = Popen(cmd.split(), shell=False, stdout=DEVNULL, stderr=DEVNULL)

        # other stuff

    def test1(self):
 
    def test2(self):

    def tearDown(self):
        """Cleanup everything before exiting"""

        self.modbus_server.terminate()


if __name__ == '__main__':
    unittest.main()

不幸的是,这似乎比我预期的更具挑战性。 我在 stackoverflow 上的其他主题尝试的一切都失败了:

  • 使用 Popen.kill() 而不是终止。我也尝试在 kill 或 terminate 之后“删除”,或者改用 os.kill(self.modbus_server.pid, SIGTERM)。
  • 为 Popen 命令添加或更改 args,例如 shell=True 而不是 shell=False 和 close_fds=True。
  • 使用子进程 Popen 的其他变体,如 check_output、run、call 等...
  • 使用 os.spawnl 代替子进程 Popen。

这些都不起作用。大多数时候发生的情况是服务器无法正常启动,因此所有其他测试都失败并且 modbus_server 进程没有终止(我必须手动杀死它)。

你有什么想法吗?谢谢。

【问题讨论】:

    标签: python-3.x subprocess python-unittest pymodbus


    【解决方案1】:

    我将分享我如何解决我的问题以及到目前为止我学到了什么:

    关于在运行测试时尝试使 modbus TCP 服务器作为子进程运行,您需要更改一些内容以使其正常工作。

    第一件事是使用“setUpClass”和“tearDownClass”而不是setUp和tearDown,(您也可以同时使用它们,但在我的情况下我需要前两个),以便您可以运行服务器的设置对所有测试套件只进行一次,而不是在每个测试用例之前和之后。不幸的是,setUpClass 和 tearDownClass 的语法并不是那么简单。这个答案对我帮助很大:Run setUp only once for a set of automated tests

    第二件事是关于 TCP 套接字的。基本上,我想确保我的测试运行良好并连续运行几次。因此,有时一切正常,有时却失败了。过了一会儿,我发现如果我在再次尝试之前至少等待一分钟就运行测试,它们将会失败。 这是由于本地地址和端口 5020 上的 modbus 服务器绑定的 TCP 套接字的 TIME_WAIT(默认设置为 60 秒)。如果您想在之前使用的相同 TCP 地址和端口上重新绑定套接字,则必须等待 60 秒。这个答案有助于理解为什么会发生这种情况:Setting TIME_WAIT TCP

    在弄清楚如何让所有这些东西协同工作后,我决定使用模拟,因为我的解决方案对我的口味来说太老套了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-09
      • 2020-05-23
      • 1970-01-01
      • 2010-10-19
      • 2021-09-11
      • 1970-01-01
      • 2020-07-10
      • 2015-09-10
      相关资源
      最近更新 更多