如何对pymodbus串口RTU服务器进行真实串口下的pytest测试?
问题根因分析
- 核心错误是测试用例中不必要的mock阻断了服务端的正常运行逻辑:你mock了
twisted.internet.serialport.SerialPort和twisted.internet.reactor,这两个是pymodbus异步RTU服务的核心依赖,mock后服务端的事件循环不会真实运行,也无法读取串口数据,因此完全收不到客户端的写入请求,寄存器值停留在初始默认值,解码后就是日志中的4.775518667735688e-39。 - 次要问题是缺少服务启动等待逻辑:服务线程启动后需要少量时间完成初始化、打开串口并进入监听状态,立即发请求会导致请求丢失。
修复方案
- 移除所有对twisted相关组件的mock,让服务端可以正常运行事件循环和串口通信逻辑
- 服务启动后增加100~200ms的等待时间,确保初始化完成
- 测试结束后主动停止服务、关闭pty文件描述符,避免资源泄漏
- 显式指定客户端从站地址,避免地址不匹配导致请求被忽略
修复后测试代码
import time import os def test_modbus_rtu_server_get_P_target_float32_should_be_big_endian_encoded() -> None: test_server_timeout = 1 test_server_baudrate = 9600 m, s = os.openpty() # 初始化并启动服务 server = ModbusRTUServer(os.ttyname(s), test_server_timeout, test_server_baudrate) server.run_server() # 等待服务初始化完成 time.sleep(0.2) try: val_f = -3.33 builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big) builder.add_32bit_float(val_f) client = ModbusSerialClient( method='rtu', baudrate=test_server_baudrate, timeout=test_server_timeout, port=os.ttyname(m), # 显式指定从站地址与服务端匹配 unit=0 ) client.connect() assert client.is_socket_open() == True # 写入寄存器 resp = client.write_registers( ModbusRTUServer.P_target_address, builder.to_registers(), unit=0 ) # 先校验写入请求成功 assert not resp.isError() # 校验值一致性 read_val = server.get_P_target_float32() assert read_val >= val_f - 0.01 assert read_val <= val_f + 0.01 finally: # 释放资源 client.close() server.stop_server() os.close(m) os.close(s)
注意:如果你的服务端配置的默认从站ID不是0,可以将上述代码中的
unit=0修改为对应值即可。
内容的提问来源于stack exchange,提问作者JAR
相关产品推荐
相关产品推荐

