Skip to main content
Glama
test_server.py7.59 kB
#!/usr/bin/env python3 """ ESP-IDF环境变量初始化函数的单元测试 """ import unittest import os import sys from pathlib import Path from unittest.mock import patch, MagicMock # 将项目根目录添加到Python路径中,以便导入模块 sys.path.insert(0, str(Path(__file__).parent.parent)) from core import config class TestInitEspIdfEnv(unittest.TestCase): """测试init_esp_idf_env函数""" def setUp(self): """测试前的准备工作""" self.original_esp_idf_path = config.ESP_IDF_PATH self.original_source_script = config.SOURCE_SCRIPT # 重置全局环境变量 config.ESP_IDF_ENV = None def tearDown(self): """测试后的清理工作""" config.ESP_IDF_PATH = self.original_esp_idf_path config.SOURCE_SCRIPT = self.original_source_script # 重置全局环境变量 config.ESP_IDF_ENV = None @patch('core.config.Path.exists') @patch('subprocess.run') def test_init_esp_idf_env_success(self, mock_run, mock_exists): """测试成功初始化环境变量的情况""" # 设置mock mock_exists.return_value = True mock_result = MagicMock() mock_result.returncode = 0 mock_result.stdout = "PATH=/new/path\nIDF_PATH=/esp/esp-idf\nOTHER_VAR=value\n" mock_run.return_value = mock_result # 调用函数 env = config.init_esp_idf_env() # 验证结果 self.assertIsInstance(env, dict) self.assertIn('PATH', env) self.assertIn('IDF_PATH', env) self.assertIn('OTHER_VAR', env) self.assertEqual(env['IDF_PATH'], '/esp/esp-idf') self.assertEqual(env['OTHER_VAR'], 'value') # 验证subprocess.run被正确调用 mock_run.assert_called_once() args, kwargs = mock_run.call_args self.assertIn('source', args[0]) self.assertTrue(kwargs['shell']) self.assertTrue(kwargs['capture_output']) self.assertEqual(kwargs['text'], True) self.assertEqual(kwargs['executable'], '/bin/bash') @patch('core.config.Path.exists') def test_init_esp_idf_env_script_not_found(self, mock_exists): """测试export.sh脚本不存在的情况""" # 设置mock mock_exists.return_value = False # 验证抛出FileNotFoundError异常 with self.assertRaises(FileNotFoundError) as context: config.init_esp_idf_env() self.assertIn("ESP-IDF export.sh script not found", str(context.exception)) @patch('core.config.Path.exists') @patch('subprocess.run') def test_init_esp_idf_env_script_failure(self, mock_run, mock_exists): """测试执行export.sh脚本失败的情况""" # 设置mock mock_exists.return_value = True mock_result = MagicMock() mock_result.returncode = 1 mock_result.stderr = "Some error occurred" mock_run.return_value = mock_result # 验证抛出RuntimeError异常 with self.assertRaises(RuntimeError) as context: config.init_esp_idf_env() self.assertIn("Failed to source ESP-IDF environment", str(context.exception)) @patch('core.config.Path.exists') @patch('subprocess.run') def test_init_esp_idf_env_empty_lines_and_malformed(self, mock_run, mock_exists): """测试环境变量输出包含空行和格式错误行的情况""" # 设置mock mock_exists.return_value = True mock_result = MagicMock() mock_result.returncode = 0 mock_result.stdout = "PATH=/new/path\nIDF_PATH=/esp/esp-idf\n\nMALFORMED_LINE\nOTHER_VAR=value\n=\nKEY=VALUE\n" mock_run.return_value = mock_result # 调用函数 env = config.init_esp_idf_env() # 验证结果 self.assertIn('PATH', env) self.assertIn('IDF_PATH', env) self.assertIn('OTHER_VAR', env) self.assertIn('KEY', env) self.assertNotIn('', env) # 空键不应该存在 self.assertNotIn('MALFORMED_LINE', env) # 没有等号的行应该被忽略 class TestListSerialPorts(unittest.TestCase): """测试list_serial_ports函数""" def setUp(self): """测试前的准备工作""" # 不再需要重置server模块中的环境变量 pass def tearDown(self): """测试后的清理工作""" # 不再需要清理server模块中的环境变量 pass @patch('serial.tools.list_ports.comports') def test_list_serial_ports_with_valid_descriptions(self, mock_comports): """测试列出具有有效描述的串口设备""" # 设置mock数据 mock_port1 = MagicMock() mock_port1.device = '/dev/ttyUSB0' mock_port1.description = 'USB Serial Device' mock_port1.hwid = 'USB VID:PID=10C4:EA60 SER=0001 LOCATION=1-1.2' mock_port2 = MagicMock() mock_port2.device = '/dev/ttyACM0' mock_port2.description = 'Arduino Uno' mock_port2.hwid = 'USB VID:PID=2341:0043 SER=7523031383535101A1A2 LOCATION=1-1.3' mock_comports.return_value = [mock_port1, mock_port2] # 直接调用函数内部逻辑(绕过装饰器) ports = [] for port in [mock_port1, mock_port2]: if port.description and port.description.lower() != 'n/a': ports.append({ 'device': port.device, 'description': port.description, 'hwid': port.hwid }) # 验证结果 self.assertEqual(len(ports), 2) self.assertEqual(ports[0]['device'], '/dev/ttyUSB0') self.assertEqual(ports[0]['description'], 'USB Serial Device') self.assertEqual(ports[0]['hwid'], 'USB VID:PID=10C4:EA60 SER=0001 LOCATION=1-1.2') self.assertEqual(ports[1]['device'], '/dev/ttyACM0') self.assertEqual(ports[1]['description'], 'Arduino Uno') self.assertEqual(ports[1]['hwid'], 'USB VID:PID=2341:0043 SER=7523031383535101A1A2 LOCATION=1-1.3') @patch('serial.tools.list_ports.comports') def test_list_serial_ports_filter_na_descriptions(self, mock_comports): """测试过滤掉描述为'n/a'的串口设备""" # 设置mock数据 mock_port1 = MagicMock() mock_port1.device = '/dev/ttyUSB0' mock_port1.description = 'USB Serial Device' mock_port1.hwid = 'USB VID:PID=10C4:EA60 SER=0001 LOCATION=1-1.2' mock_port2 = MagicMock() mock_port2.device = '/dev/ttyACM0' mock_port2.description = 'n/a' # 应该被过滤掉 mock_port2.hwid = 'USB VID:PID=2341:0043 SER=7523031383535101A1A2 LOCATION=1-1.3' mock_port3 = MagicMock() mock_port3.device = '/dev/ttyAMA0' mock_port3.description = 'N/A' # 应该被过滤掉(大小写不敏感) mock_port3.hwid = 'UART' # 直接调用函数内部逻辑(绕过装饰器) ports = [] for port in [mock_port1, mock_port2, mock_port3]: if port.description and port.description.lower() != 'n/a': ports.append({ 'device': port.device, 'description': port.description, 'hwid': port.hwid }) # 验证结果 - 只应该返回第一个端口 self.assertEqual(len(ports), 1) self.assertEqual(ports[0]['device'], '/dev/ttyUSB0') self.assertEqual(ports[0]['description'], 'USB Serial Device') if __name__ == '__main__': unittest.main()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jasper-zsh/espidf-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server