| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import pytest
- import sys
- import os
- from unittest.mock import MagicMock, patch
- # 添加项目根目录到Python路径
- sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
- from modules.serial_port import SerialPort
- class TestSerialPort:
-
- def setup_method(self):
- """每个测试方法执行前的设置"""
- # 创建SerialPort实例
- self.serial_port = SerialPort()
- # 模拟数据处理和状态处理回调
- self.data_callback = MagicMock()
- self.status_callback = MagicMock()
- self.serial_port.set_data_callback(self.data_callback)
- self.serial_port.set_status_callback(self.status_callback)
-
- def teardown_method(self):
- """每个测试方法执行后的清理"""
- # 确保断开连接
- self.serial_port.disconnect()
-
- @patch('modules.serial_port.serial.Serial')
- def test_connect_success(self, mock_serial):
- """测试成功连接串口"""
- # 模拟serial.Serial返回一个有效的串口对象
- mock_serial_instance = MagicMock()
- mock_serial.return_value = mock_serial_instance
-
- # 调用connect方法
- success, message = self.serial_port.connect('COM1', 9600)
-
- # 验证结果
- assert success is True
- assert message == "串口连接成功"
- mock_serial.assert_called_once_with(port='COM1', baudrate=9600, timeout=1)
- # 验证状态回调被调用,且状态为True
- self.status_callback.assert_called_once_with(True)
-
- @patch('modules.serial_port.serial.Serial')
- def test_connect_failure(self, mock_serial):
- """测试连接串口失败"""
- # 模拟serial.Serial抛出异常
- mock_serial.side_effect = Exception("串口未找到")
-
- # 调用connect方法
- success, message = self.serial_port.connect('COM1', 9600)
-
- # 验证结果
- assert success is False
- assert "连接失败" in message
- mock_serial.assert_called_once_with(port='COM1', baudrate=9600, timeout=1)
- # 验证状态回调被调用,且状态为False
- self.status_callback.assert_called_once_with(False)
-
- @patch('modules.serial_port.serial.Serial')
- def test_disconnect(self, mock_serial):
- """测试断开串口连接"""
- # 模拟serial.Serial返回一个有效的串口对象
- mock_serial_instance = MagicMock()
- mock_serial.return_value = mock_serial_instance
-
- # 先连接,再断开
- self.serial_port.connect('COM1', 9600)
- # 重置状态回调的调用记录
- self.status_callback.reset_mock()
-
- # 调用disconnect方法
- self.serial_port.disconnect()
-
- # 验证结果
- mock_serial_instance.close.assert_called_once()
- # 验证状态回调被调用,且状态为False
- self.status_callback.assert_called_once_with(False)
-
- @patch('modules.serial_port.serial.Serial')
- def test_disconnect_not_connected(self, mock_serial):
- """测试断开未连接的串口"""
- # 不连接直接断开
- self.serial_port.disconnect()
-
- # 验证状态回调没有被调用
- self.status_callback.assert_not_called()
-
- @patch('modules.serial_port.serial.Serial')
- def test_send_data_success(self, mock_serial):
- """测试成功发送数据"""
- # 模拟serial.Serial返回一个有效的串口对象
- mock_serial_instance = MagicMock()
- mock_serial.return_value = mock_serial_instance
-
- # 先连接
- self.serial_port.connect('COM1', 9600)
-
- # 调用send_data方法
- test_data = "Hello, Serial!"
- success, message = self.serial_port.send_data(test_data)
-
- # 验证结果
- assert success is True
- assert message == "数据发送成功"
- mock_serial_instance.write.assert_called_once_with(test_data.encode())
-
- @patch('modules.serial_port.serial.Serial')
- def test_send_data_failure(self, mock_serial):
- """测试发送数据失败"""
- # 模拟serial.Serial返回一个有效的串口对象,但write方法抛出异常
- mock_serial_instance = MagicMock()
- mock_serial_instance.write.side_effect = Exception("写入失败")
- mock_serial.return_value = mock_serial_instance
-
- # 先连接
- self.serial_port.connect('COM1', 9600)
-
- # 调用send_data方法
- test_data = "Hello, Serial!"
- success, message = self.serial_port.send_data(test_data)
-
- # 验证结果
- assert success is False
- assert "发送失败" in message
- mock_serial_instance.write.assert_called_once_with(test_data.encode())
-
- @patch('modules.serial_port.serial.Serial')
- def test_send_data_not_connected(self, mock_serial):
- """测试未连接时发送数据"""
- # 不连接直接发送数据
- test_data = "Hello, Serial!"
- success, message = self.serial_port.send_data(test_data)
-
- # 验证结果
- assert success is False
- assert message == "串口未连接"
-
- @patch('modules.serial_port.serial.Serial')
- def test_get_status(self, mock_serial):
- """测试获取串口状态"""
- # 模拟serial.Serial返回一个有效的串口对象
- mock_serial_instance = MagicMock()
- mock_serial.return_value = mock_serial_instance
-
- # 初始状态应该是False
- assert self.serial_port.get_status() is False
-
- # 连接后状态应该是True
- self.serial_port.connect('COM1', 9600)
- assert self.serial_port.get_status() is True
-
- # 断开后状态应该是False
- self.serial_port.disconnect()
- assert self.serial_port.get_status() is False
-
- @patch('modules.serial_port.serial.Serial')
- def test_receive_data(self, mock_serial):
- """测试接收数据"""
- # 模拟serial.Serial返回一个有效的串口对象,并设置readline的返回值
- mock_serial_instance = MagicMock()
- mock_serial_instance.readline.return_value = "Test data\n".encode()
- mock_serial.return_value = mock_serial_instance
-
- # 连接串口
- self.serial_port.connect('COM1', 9600)
-
- # 模拟一个接收到的数据
- # 需要手动触发内部的读取线程来接收数据,但这在单元测试中比较复杂
- # 这里我们直接调用内部的_read_serial方法来模拟
- # 注意:实际代码中可能需要修改SerialPort类,使其_read_serial方法可以从外部调用,
- # 或者添加一个专门用于测试的方法
-
- # 由于_read_serial是一个私有方法,这里我们使用patch来模拟它被调用时的行为
- with patch.object(self.serial_port, '_read_serial') as mock_read_serial:
- # 调用mock_read_serial并模拟其行为
- # 这里我们手动调用数据回调函数来模拟数据接收
- self.data_callback("Test data")
-
- # 验证数据回调被调用
- self.data_callback.assert_called_with("Test data")
- if __name__ == "__main__":
- pytest.main(["-v", __file__])
|