08ea5fbe98
添加用户管理视图、API和状态管理文件
374 lines
12 KiB
Python
374 lines
12 KiB
Python
"""测试编排器单元测试"""
|
||
|
||
import pytest
|
||
from pathlib import Path
|
||
from unittest.mock import Mock, MagicMock, patch
|
||
from apitest.orchestrator.test_orchestrator import TestOrchestrator
|
||
from apitest.models.test_models import TestCase, TestSuiteResult, HTTPMethod
|
||
from apitest.models.exceptions import TestRunException
|
||
|
||
|
||
@pytest.fixture
|
||
def mock_config_manager():
|
||
"""创建模拟配置管理器"""
|
||
config_manager = Mock()
|
||
config_manager.get_base_url.return_value = "http://localhost:8080"
|
||
config_manager.get_timeout.return_value = 30
|
||
config_manager.get_log_level.return_value = "INFO"
|
||
config_manager.get_log_format.return_value = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||
return config_manager
|
||
|
||
|
||
@pytest.fixture
|
||
def mock_logger_manager():
|
||
"""创建模拟日志管理器"""
|
||
logger_manager = Mock()
|
||
logger = Mock()
|
||
logger_manager.get_logger.return_value = logger
|
||
return logger_manager
|
||
|
||
|
||
@pytest.fixture
|
||
def test_orchestrator(mock_config_manager, mock_logger_manager):
|
||
"""创建测试编排器实例"""
|
||
return TestOrchestrator(
|
||
config_manager=mock_config_manager,
|
||
logger_manager=mock_logger_manager
|
||
)
|
||
|
||
|
||
@pytest.fixture
|
||
def sample_test_cases():
|
||
"""创建示例测试用例"""
|
||
return [
|
||
TestCase(
|
||
id="TC001",
|
||
name="测试用例1",
|
||
description="测试用例1",
|
||
module="test",
|
||
endpoint="/api/test1",
|
||
method=HTTPMethod.GET,
|
||
headers={},
|
||
enabled=True
|
||
),
|
||
TestCase(
|
||
id="TC002",
|
||
name="测试用例2",
|
||
description="测试用例2",
|
||
module="test",
|
||
endpoint="/api/test2",
|
||
method=HTTPMethod.POST,
|
||
headers={},
|
||
enabled=True
|
||
)
|
||
]
|
||
|
||
|
||
def test_init_test_orchestrator(mock_config_manager, mock_logger_manager):
|
||
"""测试初始化测试编排器"""
|
||
orchestrator = TestOrchestrator(
|
||
config_manager=mock_config_manager,
|
||
logger_manager=mock_logger_manager
|
||
)
|
||
|
||
assert orchestrator.config_manager == mock_config_manager
|
||
assert orchestrator.logger_manager == mock_logger_manager
|
||
assert orchestrator.api_client is not None
|
||
assert orchestrator.auth_manager is not None
|
||
assert orchestrator.validation_engine is not None
|
||
assert orchestrator.test_engine is not None
|
||
assert orchestrator.report_manager is not None
|
||
assert orchestrator.logger is not None
|
||
|
||
|
||
def test_init_test_orchestrator_without_managers():
|
||
"""测试初始化测试编排器(不提供管理器)"""
|
||
mock_logger = Mock()
|
||
orchestrator = TestOrchestrator(logger=mock_logger)
|
||
|
||
assert orchestrator.config_manager is not None
|
||
assert orchestrator.logger_manager is not None
|
||
assert orchestrator.api_client is not None
|
||
assert orchestrator.auth_manager is not None
|
||
assert orchestrator.validation_engine is not None
|
||
assert orchestrator.test_engine is not None
|
||
assert orchestrator.report_manager is not None
|
||
assert orchestrator.logger is not None
|
||
|
||
|
||
def test_load_test_cases_success(test_orchestrator, tmp_path):
|
||
"""测试加载测试用例(成功)"""
|
||
import json
|
||
|
||
test_data = [
|
||
{
|
||
"id": "TC001",
|
||
"name": "测试用例1",
|
||
"description": "测试用例1",
|
||
"module": "test",
|
||
"endpoint": "/api/test1",
|
||
"method": "GET",
|
||
"headers": {},
|
||
"enabled": True
|
||
},
|
||
{
|
||
"id": "TC002",
|
||
"name": "测试用例2",
|
||
"description": "测试用例2",
|
||
"module": "test",
|
||
"endpoint": "/api/test2",
|
||
"method": "POST",
|
||
"headers": {},
|
||
"enabled": True
|
||
}
|
||
]
|
||
|
||
test_file = tmp_path / "test_cases.json"
|
||
with open(test_file, "w", encoding="utf-8") as f:
|
||
json.dump(test_data, f)
|
||
|
||
test_cases = test_orchestrator.load_test_cases(test_file)
|
||
|
||
assert len(test_cases) == 2
|
||
assert test_cases[0].id == "TC001"
|
||
assert test_cases[1].id == "TC002"
|
||
|
||
|
||
def test_load_test_cases_file_not_found(test_orchestrator, tmp_path):
|
||
"""测试加载测试用例(文件不存在)"""
|
||
test_file = tmp_path / "nonexistent.json"
|
||
|
||
with pytest.raises(TestRunException) as exc_info:
|
||
test_orchestrator.load_test_cases(test_file)
|
||
|
||
assert "测试用例文件不存在" in str(exc_info.value)
|
||
|
||
|
||
def test_load_test_cases_invalid_json(test_orchestrator, tmp_path):
|
||
"""测试加载测试用例(无效JSON)"""
|
||
test_file = tmp_path / "invalid.json"
|
||
with open(test_file, "w", encoding="utf-8") as f:
|
||
f.write("invalid json")
|
||
|
||
with pytest.raises(TestRunException) as exc_info:
|
||
test_orchestrator.load_test_cases(test_file)
|
||
|
||
assert "加载测试用例失败" in str(exc_info.value)
|
||
|
||
|
||
def test_load_test_cases_with_all_fields(test_orchestrator, tmp_path):
|
||
"""测试加载测试用例(包含所有字段)"""
|
||
import json
|
||
|
||
test_data = [
|
||
{
|
||
"id": "TC001",
|
||
"name": "测试用例1",
|
||
"description": "测试用例1",
|
||
"module": "test",
|
||
"endpoint": "/api/test1",
|
||
"method": "GET",
|
||
"headers": {"Content-Type": "application/json"},
|
||
"params": {"param1": "value1"},
|
||
"body": {"key": "value"},
|
||
"dependencies": ["TC002"],
|
||
"tags": ["tag1", "tag2"],
|
||
"priority": 1,
|
||
"enabled": True,
|
||
"timeout": 10,
|
||
"validations": [{"type": "status_code", "value": 200}],
|
||
"extract_config": [{"type": "extract", "field": "id", "var_name": "user_id"}]
|
||
}
|
||
]
|
||
|
||
test_file = tmp_path / "test_cases.json"
|
||
with open(test_file, "w", encoding="utf-8") as f:
|
||
json.dump(test_data, f)
|
||
|
||
test_cases = test_orchestrator.load_test_cases(test_file)
|
||
|
||
assert len(test_cases) == 1
|
||
assert test_cases[0].id == "TC001"
|
||
assert test_cases[0].method == HTTPMethod.GET
|
||
assert test_cases[0].headers == {"Content-Type": "application/json"}
|
||
assert test_cases[0].params == {"param1": "value1"}
|
||
assert test_cases[0].body == {"key": "value"}
|
||
assert test_cases[0].dependencies == ["TC002"]
|
||
assert test_cases[0].tags == ["tag1", "tag2"]
|
||
assert test_cases[0].priority == 1
|
||
assert test_cases[0].enabled == True
|
||
assert test_cases[0].timeout == 10
|
||
assert len(test_cases[0].validations) == 1
|
||
|
||
|
||
def test_run_test_suite_success(test_orchestrator, sample_test_cases, tmp_path):
|
||
"""测试运行测试套件(成功)"""
|
||
report_path = tmp_path / "test_report.html"
|
||
|
||
with patch.object(test_orchestrator.test_engine, 'execute_test_suite') as mock_execute:
|
||
mock_result = Mock(spec=TestSuiteResult)
|
||
mock_result.suite_name = "Test Suite"
|
||
mock_result.total = 2
|
||
mock_result.passed = 2
|
||
mock_result.failed = 0
|
||
mock_result.skipped = 0
|
||
mock_result.pass_rate = 100.0
|
||
mock_result.duration = 1.0
|
||
mock_execute.return_value = mock_result
|
||
|
||
result = test_orchestrator.run_test_suite(
|
||
sample_test_cases,
|
||
generate_report=False
|
||
)
|
||
|
||
assert result == mock_result
|
||
mock_execute.assert_called_once_with(sample_test_cases, stop_on_failure=False)
|
||
|
||
|
||
def test_run_test_suite_with_report(test_orchestrator, sample_test_cases, tmp_path):
|
||
"""测试运行测试套件(生成报告)"""
|
||
report_path = tmp_path / "test_report.html"
|
||
|
||
with patch.object(test_orchestrator.test_engine, 'execute_test_suite') as mock_execute, \
|
||
patch.object(test_orchestrator.report_manager, 'generate_html_report') as mock_report:
|
||
mock_result = Mock(spec=TestSuiteResult)
|
||
mock_result.suite_name = "Test Suite"
|
||
mock_result.total = 2
|
||
mock_result.passed = 2
|
||
mock_result.failed = 0
|
||
mock_result.skipped = 0
|
||
mock_result.pass_rate = 100.0
|
||
mock_result.duration = 1.0
|
||
mock_execute.return_value = mock_result
|
||
|
||
result = test_orchestrator.run_test_suite(
|
||
sample_test_cases,
|
||
generate_report=True,
|
||
report_format="html",
|
||
report_path=report_path
|
||
)
|
||
|
||
assert result == mock_result
|
||
mock_report.assert_called_once()
|
||
|
||
|
||
def test_run_test_suite_stop_on_failure(test_orchestrator, sample_test_cases):
|
||
"""测试运行测试套件(失败时停止)"""
|
||
with patch.object(test_orchestrator.test_engine, 'execute_test_suite') as mock_execute:
|
||
mock_result = Mock(spec=TestSuiteResult)
|
||
mock_result.suite_name = "Test Suite"
|
||
mock_result.total = 2
|
||
mock_result.passed = 1
|
||
mock_result.failed = 1
|
||
mock_result.skipped = 0
|
||
mock_result.pass_rate = 50.0
|
||
mock_result.duration = 0.5
|
||
mock_execute.return_value = mock_result
|
||
|
||
result = test_orchestrator.run_test_suite(
|
||
sample_test_cases,
|
||
stop_on_failure=True,
|
||
generate_report=False
|
||
)
|
||
|
||
assert result == mock_result
|
||
mock_execute.assert_called_once_with(sample_test_cases, stop_on_failure=True)
|
||
|
||
|
||
def test_run_test_suite_by_filter_module(test_orchestrator, sample_test_cases):
|
||
"""测试按模块过滤运行测试套件"""
|
||
with patch.object(test_orchestrator.test_engine, 'execute_test_cases_by_filter') as mock_execute:
|
||
mock_result = Mock(spec=TestSuiteResult)
|
||
mock_result.suite_name = "Test Suite"
|
||
mock_result.total = 2
|
||
mock_result.passed = 2
|
||
mock_result.failed = 0
|
||
mock_result.skipped = 0
|
||
mock_result.pass_rate = 100.0
|
||
mock_result.duration = 1.0
|
||
mock_execute.return_value = mock_result
|
||
|
||
result = test_orchestrator.run_test_suite_by_filter(
|
||
sample_test_cases,
|
||
module_filter="test",
|
||
generate_report=False
|
||
)
|
||
|
||
assert result == mock_result
|
||
mock_execute.assert_called_once_with(
|
||
sample_test_cases,
|
||
module_filter="test",
|
||
tag_filter=None,
|
||
priority_filter=None
|
||
)
|
||
|
||
|
||
def test_run_test_suite_by_filter_tag(test_orchestrator, sample_test_cases):
|
||
"""测试按标签过滤运行测试套件"""
|
||
with patch.object(test_orchestrator.test_engine, 'execute_test_cases_by_filter') as mock_execute:
|
||
mock_result = Mock(spec=TestSuiteResult)
|
||
mock_result.suite_name = "Test Suite"
|
||
mock_result.total = 2
|
||
mock_result.passed = 2
|
||
mock_result.failed = 0
|
||
mock_result.skipped = 0
|
||
mock_result.pass_rate = 100.0
|
||
mock_result.duration = 1.0
|
||
mock_execute.return_value = mock_result
|
||
|
||
result = test_orchestrator.run_test_suite_by_filter(
|
||
sample_test_cases,
|
||
tag_filter=["smoke"],
|
||
generate_report=False
|
||
)
|
||
|
||
assert result == mock_result
|
||
mock_execute.assert_called_once_with(
|
||
sample_test_cases,
|
||
module_filter=None,
|
||
tag_filter=["smoke"],
|
||
priority_filter=None
|
||
)
|
||
|
||
|
||
def test_run_test_suite_by_filter_priority(test_orchestrator, sample_test_cases):
|
||
"""测试按优先级过滤运行测试套件"""
|
||
with patch.object(test_orchestrator.test_engine, 'execute_test_cases_by_filter') as mock_execute:
|
||
mock_result = Mock(spec=TestSuiteResult)
|
||
mock_result.suite_name = "Test Suite"
|
||
mock_result.total = 2
|
||
mock_result.passed = 2
|
||
mock_result.failed = 0
|
||
mock_result.skipped = 0
|
||
mock_result.pass_rate = 100.0
|
||
mock_result.duration = 1.0
|
||
mock_execute.return_value = mock_result
|
||
|
||
result = test_orchestrator.run_test_suite_by_filter(
|
||
sample_test_cases,
|
||
priority_filter=1,
|
||
generate_report=False
|
||
)
|
||
|
||
assert result == mock_result
|
||
mock_execute.assert_called_once_with(
|
||
sample_test_cases,
|
||
module_filter=None,
|
||
tag_filter=None,
|
||
priority_filter=1
|
||
)
|
||
|
||
|
||
def test_set_base_url(test_orchestrator):
|
||
"""测试设置基础URL"""
|
||
test_orchestrator.set_base_url("http://new-api.example.com")
|
||
|
||
assert test_orchestrator.api_client.base_url == "http://new-api.example.com"
|
||
|
||
|
||
def test_set_auth_token(test_orchestrator):
|
||
"""测试设置认证令牌"""
|
||
test_orchestrator.set_auth_token("test-token-123")
|
||
|
||
assert test_orchestrator.auth_manager.get_token() == "test-token-123"
|