树莓派4多USB串口转换器pyserial时序异常问题求助
串口自动化测试批量运行时随机失败问题
环境配置
- 树莓派4连接带外部供电的USB集线器
- 集线器外接5个USB-Serial转换器,每个转换器连接一台低功耗STM32设备,设备通过转换器供电
测试场景
使用pytest实现自动化测试:向设备发送命令并等待响应,因设备间存在交互,需近乎同时向多台设备发送命令。
问题现象
- 手动逐个运行测试时,整套设备工作正常
- 批量串行运行pytest时,第一个测试总能成功,其余测试随机失败;调整代码中的延迟时间会改变失败的测试用例,不修改代码则失败模式固定
- 所有串口、设备、布线均已单独验证正常(部分测试会用到全部设备且多次通过)
调试发现
Python代码中serial.write()返回成功,但示波器确认物理线路有时无数据传输;该现象仅随机出现,部分测试/延迟配置下数据可正常传输,排除示波器设置问题。
关键代码片段
串口通信类实现
class Link_Serial(linkcore.LinkCore): def __init__(self, comport, packet_queue, ack_queue, id_queue, link_address): super().__init__(packet_queue, ack_queue, id_queue, link_address) self.serial = serial.Serial(port=comport, baudrate=115200) self.rx_buffer = [] self.received_packets = [] self.events = [] def on_transmit(self, tx_data): print("TX", self.serial.name, self.serial.is_open, tx_data) time.sleep(0.02) self.serial.write(tx_data) self.tx_done() return 1 def reset(self): self.rx_buffer.clear() self.received_packets.clear() self.events.clear() self.serial.reset_input_buffer() self.serial.reset_output_buffer() super().reset()
微调
time.sleep(...)的数值会导致不同测试失败
pytest fixture初始化逻辑
def get_module_n(n): if n >= len(modules) or n < 0: raise if radios[n] is None: info = modules[n] radios[n] = Link_Serial(...) radios[n].reset() return radios[n] def stop_module(radio): radio.power_off() radio.reset() ... @pytest.fixture def radio0(): ctrl = rack.get_module_n(0) yield ctrl rack.stop_module(ctrl) @pytest.fixture def radio1(): ctrl = rack.get_module_n(1) yield ctrl rack.stop_module(ctrl) ...
时序敏感测试用例示例
def test_many_senders_one_receiver(radio0, radio1, radio2, radio3, radio4): time.sleep(0.1) radio0.power_on() radio1.power_on() radio2.power_on() radio3.power_on() radio4.power_on() time.sleep(0.1) message = [1, 2, 3, 4, 5, 6] for radio in [radio1, radio2, radio3, radio4]: radio.send_packet(radio0.id, message) for _ in range(0, 1000): rack.run_links([radio0, radio1, radio2, radio3, radio4], 10) if radio0.get_events().count(LINK_DATA_RECEIVED) == 4: break assert LINK_DATA_ACKED in radio1.get_events() print(radio2.get_events()) assert LINK_DATA_ACKED in radio2.get_events() assert LINK_DATA_ACKED in radio3.get_events() assert LINK_DATA_ACKED in radio4.get_events() assert radio0.get_events().count(LINK_DATA_RECEIVED) == 4 assert len(radio0.get_packets()) == 4
尝试过的调整
最初设置为每个测试初始化新的Link_Serial对象,仅第一个测试成功(手动单独运行所有测试正常);改为全局初始化一次对象,测试间仅执行reset操作,问题仍存在。
内容的提问来源于stack exchange,提问作者Ou Tsei
相关产品推荐
相关产品推荐

