| """ |
| SSHOUT模块初始化和工厂函数的完整测试覆盖 |
| """ |
| |
| import pytest |
| from unittest.mock import Mock, patch |
| |
| import sys |
| import os |
| sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../../../src')) |
| |
| from claude_agent.sshout import ( |
| create_sshout_integration, |
| SSHOUTIntegration, |
| SSHOUTConnection, |
| SSHOUTMessage, |
| SSHOUTApiClient, |
| SSHOUTApiIntegration, |
| ApiSSHOUTMessage |
| ) |
| |
| |
| class TestSSHOUTModuleInit: |
| """测试SSHOUT模块初始化""" |
| |
| def test_imports_available(self): |
| """测试所有导入的类都可用""" |
| # 验证所有导出的类都存在 |
| assert SSHOUTIntegration is not None |
| assert SSHOUTConnection is not None |
| assert SSHOUTMessage is not None |
| assert SSHOUTApiClient is not None |
| assert SSHOUTApiIntegration is not None |
| assert ApiSSHOUTMessage is not None |
| |
| def test_all_exports(self): |
| """测试__all__导出列表""" |
| from claude_agent.sshout import __all__ |
| |
| expected_exports = [ |
| 'SSHOUTIntegration', |
| 'SSHOUTConnection', |
| 'SSHOUTMessage', |
| 'SSHOUTApiClient', |
| 'SSHOUTApiIntegration', |
| 'ApiSSHOUTMessage', |
| 'create_sshout_integration' |
| ] |
| |
| assert __all__ == expected_exports |
| |
| |
| class TestCreateSSHOUTIntegration: |
| """测试create_sshout_integration工厂函数""" |
| |
| @pytest.fixture |
| def mock_agent(self): |
| """创建模拟Agent""" |
| return Mock() |
| |
| @pytest.fixture |
| def mock_config_manager(self): |
| """创建模拟配置管理器""" |
| config_manager = Mock() |
| config_manager.get_sshout_config.return_value = {} |
| return config_manager |
| |
| def test_create_api_integration_default(self, mock_agent, mock_config_manager): |
| """测试创建API集成(默认模式)""" |
| # 默认配置使用API模式 |
| mock_config_manager.get_sshout_config.return_value = {} |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with patch('claude_agent.sshout.SSHOUTApiIntegration') as mock_api_integration: |
| result = create_sshout_integration(mock_agent) |
| |
| # 应该创建API集成 |
| mock_api_integration.assert_called_once_with(mock_agent, None) |
| assert result == mock_api_integration.return_value |
| |
| def test_create_api_integration_explicit(self, mock_agent, mock_config_manager): |
| """测试显式创建API集成""" |
| mock_config_manager.get_sshout_config.return_value = { |
| 'connection_mode': 'api' |
| } |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with patch('claude_agent.sshout.SSHOUTApiIntegration') as mock_api_integration: |
| result = create_sshout_integration(mock_agent, 'test_config') |
| |
| mock_api_integration.assert_called_once_with(mock_agent, 'test_config') |
| assert result == mock_api_integration.return_value |
| |
| def test_create_ssh_integration(self, mock_agent, mock_config_manager): |
| """测试创建SSH集成""" |
| mock_config_manager.get_sshout_config.return_value = { |
| 'connection_mode': 'ssh' |
| } |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with patch('claude_agent.sshout.SSHOUTIntegration') as mock_ssh_integration: |
| result = create_sshout_integration(mock_agent, 'ssh_config') |
| |
| mock_ssh_integration.assert_called_once_with(mock_agent, 'ssh_config') |
| assert result == mock_ssh_integration.return_value |
| |
| def test_create_integration_invalid_mode(self, mock_agent, mock_config_manager): |
| """测试创建集成 - 无效模式""" |
| mock_config_manager.get_sshout_config.return_value = { |
| 'connection_mode': 'invalid_mode' |
| } |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with pytest.raises(ValueError, match="不支持的SSHOUT连接模式: invalid_mode"): |
| create_sshout_integration(mock_agent) |
| |
| def test_create_integration_with_config_name(self, mock_agent, mock_config_manager): |
| """测试使用配置名称创建集成""" |
| config_name = "production" |
| mock_config_manager.get_sshout_config.return_value = { |
| 'connection_mode': 'api' |
| } |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager) as mock_get_config: |
| with patch('claude_agent.sshout.SSHOUTApiIntegration') as mock_api_integration: |
| result = create_sshout_integration(mock_agent, config_name) |
| |
| # 应该使用指定的配置名称 |
| mock_get_config.assert_called_once_with(config_name) |
| mock_api_integration.assert_called_once_with(mock_agent, config_name) |
| |
| def test_create_integration_config_error(self, mock_agent): |
| """测试配置加载错误""" |
| with patch('claude_agent.utils.config.get_config_manager', side_effect=Exception("配置加载失败")): |
| with pytest.raises(Exception, match="配置加载失败"): |
| create_sshout_integration(mock_agent) |
| |
| def test_create_integration_missing_config(self, mock_agent, mock_config_manager): |
| """测试缺失配置""" |
| # 配置管理器返回None |
| mock_config_manager.get_sshout_config.side_effect = Exception("配置不存在") |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with pytest.raises(Exception, match="配置不存在"): |
| create_sshout_integration(mock_agent) |
| |
| def test_create_integration_none_agent(self, mock_config_manager): |
| """测试None Agent参数""" |
| mock_config_manager.get_sshout_config.return_value = {} |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with patch('claude_agent.sshout.SSHOUTApiIntegration') as mock_api_integration: |
| result = create_sshout_integration(None) |
| |
| # 应该传递None给集成类 |
| mock_api_integration.assert_called_once_with(None, None) |
| |
| def test_create_integration_complex_config(self, mock_agent, mock_config_manager): |
| """测试复杂配置""" |
| complex_config = { |
| 'connection_mode': 'api', |
| 'server': { |
| 'hostname': 'test.example.com', |
| 'port': 22333 |
| }, |
| 'ssh_key': { |
| 'private_key_path': '/path/to/key' |
| } |
| } |
| mock_config_manager.get_sshout_config.return_value = complex_config |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with patch('claude_agent.sshout.SSHOUTApiIntegration') as mock_api_integration: |
| result = create_sshout_integration(mock_agent) |
| |
| # 应该正确创建API集成,配置细节由集成类处理 |
| mock_api_integration.assert_called_once_with(mock_agent, None) |
| |
| def test_create_integration_case_insensitive_mode(self, mock_agent, mock_config_manager): |
| """测试连接模式的大小写敏感性""" |
| mock_config_manager.get_sshout_config.return_value = { |
| 'connection_mode': 'API' # 大写 |
| } |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| # 这应该抛出错误,因为当前实现区分大小写 |
| with pytest.raises(ValueError, match="不支持的SSHOUT连接模式: API"): |
| create_sshout_integration(mock_agent) |
| |
| def test_create_integration_empty_config(self, mock_agent, mock_config_manager): |
| """测试空配置""" |
| mock_config_manager.get_sshout_config.return_value = {} |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with patch('claude_agent.sshout.SSHOUTApiIntegration') as mock_api_integration: |
| result = create_sshout_integration(mock_agent) |
| |
| # 空配置应该默认为API模式 |
| mock_api_integration.assert_called_once_with(mock_agent, None) |
| |
| def test_create_integration_config_manager_call(self, mock_agent, mock_config_manager): |
| """测试配置管理器调用""" |
| mock_config_manager.get_sshout_config.return_value = {'connection_mode': 'api'} |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager) as mock_get_config: |
| with patch('claude_agent.sshout.SSHOUTApiIntegration'): |
| create_sshout_integration(mock_agent, 'test_config') |
| |
| # 验证配置管理器被正确调用 |
| mock_get_config.assert_called_once_with('test_config') |
| mock_config_manager.get_sshout_config.assert_called_once() |
| |
| def test_create_integration_factory_pattern(self, mock_agent, mock_config_manager): |
| """测试工厂模式的完整性""" |
| test_cases = [ |
| ('api', 'SSHOUTApiIntegration'), |
| ('ssh', 'SSHOUTIntegration') |
| ] |
| |
| for mode, expected_class in test_cases: |
| mock_config_manager.get_sshout_config.return_value = { |
| 'connection_mode': mode |
| } |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with patch(f'claude_agent.sshout.{expected_class}') as mock_integration: |
| result = create_sshout_integration(mock_agent) |
| |
| # 应该创建正确的集成类型 |
| mock_integration.assert_called_once_with(mock_agent, None) |
| assert result == mock_integration.return_value |
| |
| def test_module_docstring_consistency(self): |
| """测试模块文档字符串的一致性""" |
| import claude_agent.sshout as sshout_module |
| |
| # 验证模块有文档字符串 |
| assert sshout_module.__doc__ is not None |
| assert "SSHOUT聊天室集成支持" in sshout_module.__doc__ |
| assert "SSH模式" in sshout_module.__doc__ |
| assert "API模式" in sshout_module.__doc__ |
| |
| def test_function_signature_consistency(self, mock_agent): |
| """测试函数签名的一致性""" |
| # 测试可选参数的默认值 |
| with patch('claude_agent.utils.config.get_config_manager') as mock_get_config: |
| # 设置正确的mock返回值 |
| mock_config_manager = Mock() |
| mock_config_manager.get_sshout_config.return_value = {'connection_mode': 'api'} |
| mock_get_config.return_value = mock_config_manager |
| |
| with patch('claude_agent.sshout.SSHOUTApiIntegration'): |
| # 不传config_name |
| create_sshout_integration(mock_agent) |
| mock_get_config.assert_called_with(None) |
| |
| # 传入config_name |
| create_sshout_integration(mock_agent, "test") |
| mock_get_config.assert_called_with("test") |
| |
| def test_integration_creation_edge_cases(self, mock_agent, mock_config_manager): |
| """测试集成创建的边界情况""" |
| # 测试配置值为None的情况 |
| mock_config_manager.get_sshout_config.return_value = { |
| 'connection_mode': None |
| } |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with pytest.raises(ValueError, match="不支持的SSHOUT连接模式: None"): |
| create_sshout_integration(mock_agent) |
| |
| # 测试配置值为空字符串的情况 |
| mock_config_manager.get_sshout_config.return_value = { |
| 'connection_mode': '' |
| } |
| |
| with patch('claude_agent.utils.config.get_config_manager', return_value=mock_config_manager): |
| with pytest.raises(ValueError, match="不支持的SSHOUT连接模式: "): |
| create_sshout_integration(mock_agent) |