微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在python单元测试中对pymodbus tcp服务器进行子处理,并在执行完所有测试后将其终止?

如何解决如何在python单元测试中对pymodbus tcp服务器进行子处理,并在执行完所有测试后将其终止?

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

我现在想做的是使用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()而不是终止。我还尝试在杀死或终止后“删除”,或者改用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进程没有终止(我必须手动将其杀死)。

你有什么主意吗?谢谢。

解决方法

我将分享我如何解决问题以及到目前为止所学到的知识:

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

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

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

在弄清楚如何使所有这些东西协同工作之后,我决定使用模拟程序,因为我的解决方案似乎太笨拙了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。