首页 > 解决方案 > 如何在 python 单元测试中子处理 pymodbus tcp 服务器并在执行所有测试后终止它?

问题描述

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

我现在想做的是为执行器编写一个单元测试,使用 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 上的其他主题尝试的一切都失败了:

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

你有什么主意吗?谢谢你。

标签: python-3.xsubprocesspython-unittestpymodbus

解决方案


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

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

第一件事是使用“setUpClass”和“tearDownClass”而不是setUp和tearDown,(你也可以使用它们,但在我的情况下我需要前两个)这样你就可以运行你的服务器设置一次所有测试套件,而不是每个测试用例之前和之后。不幸的是,setUpClass 和 tearDownClass 的语法并不是那么简单。这个答案对我帮助很大:为一组自动化测试只运行一次 setUp

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

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


推荐阅读