feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
from .test_engine import TestEngine
|
||||
from .validation_engine import ValidationEngine
|
||||
|
||||
__all__ = ["TestEngine", "ValidationEngine"]
|
||||
@@ -0,0 +1,400 @@
|
||||
from typing import List, Dict, Any, Optional
|
||||
from collections import defaultdict
|
||||
from datetime import datetime
|
||||
from apitest.models.test_models import (
|
||||
TestCase, TestResult, TestSuiteResult, HTTPMethod, PerformanceMetrics
|
||||
)
|
||||
from apitest.client.api_client import APIClient
|
||||
from apitest.client.auth_manager import AuthManager
|
||||
from apitest.core.validation_engine import ValidationEngine
|
||||
from apitest.models.exceptions import TestRunException, RequestException, ValidationException
|
||||
|
||||
|
||||
class TestEngine:
|
||||
"""测试引擎"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
api_client: APIClient,
|
||||
auth_manager: Optional[AuthManager] = None,
|
||||
validation_engine: Optional[ValidationEngine] = None,
|
||||
logger=None
|
||||
):
|
||||
"""初始化测试引擎
|
||||
|
||||
Args:
|
||||
api_client: API客户端
|
||||
auth_manager: 认证管理器
|
||||
validation_engine: 验证引擎
|
||||
logger: 日志记录器
|
||||
"""
|
||||
self.api_client = api_client
|
||||
self.auth_manager = auth_manager
|
||||
self.validation_engine = validation_engine or ValidationEngine(logger)
|
||||
self.logger = logger
|
||||
self._context: Dict[str, Any] = {}
|
||||
self._dependency_map: Dict[str, List[str]] = defaultdict(list)
|
||||
self._reverse_dependency_map: Dict[str, List[str]] = defaultdict(list)
|
||||
|
||||
def set_context(self, key: str, value: Any):
|
||||
"""设置上下文变量
|
||||
|
||||
Args:
|
||||
key: 键
|
||||
value: 值
|
||||
"""
|
||||
self._context[key] = value
|
||||
if self.logger:
|
||||
self.logger.debug(f"设置上下文变量: {key}")
|
||||
|
||||
def get_context(self, key: str, default: Any = None) -> Any:
|
||||
"""获取上下文变量
|
||||
|
||||
Args:
|
||||
key: 键
|
||||
default: 默认值
|
||||
|
||||
Returns:
|
||||
值
|
||||
"""
|
||||
return self._context.get(key, default)
|
||||
|
||||
def _build_dependency_graph(self, test_cases: List[TestCase]):
|
||||
"""构建依赖关系图
|
||||
|
||||
Args:
|
||||
test_cases: 测试用例列表
|
||||
"""
|
||||
self._dependency_map.clear()
|
||||
self._reverse_dependency_map.clear()
|
||||
|
||||
for test_case in test_cases:
|
||||
for dep_id in test_case.dependencies:
|
||||
self._dependency_map[test_case.id].append(dep_id)
|
||||
self._reverse_dependency_map[dep_id].append(test_case.id)
|
||||
|
||||
if self.logger:
|
||||
self.logger.debug(f"依赖关系图构建完成: {len(self._dependency_map)} 个依赖关系")
|
||||
|
||||
def _topological_sort(self, test_cases: List[TestCase]) -> List[TestCase]:
|
||||
"""拓扑排序测试用例
|
||||
|
||||
Args:
|
||||
test_cases: 测试用例列表
|
||||
|
||||
Returns:
|
||||
排序后的测试用例列表
|
||||
|
||||
Raises:
|
||||
TestRunException: 存在循环依赖时抛出
|
||||
"""
|
||||
self._build_dependency_graph(test_cases)
|
||||
|
||||
in_degree = {tc.id: 0 for tc in test_cases}
|
||||
test_case_map = {tc.id: tc for tc in test_cases}
|
||||
|
||||
for tc in test_cases:
|
||||
for dep_id in tc.dependencies:
|
||||
if dep_id in in_degree:
|
||||
in_degree[tc.id] += 1
|
||||
|
||||
queue = [tc_id for tc_id, degree in in_degree.items() if degree == 0]
|
||||
result = []
|
||||
|
||||
while queue:
|
||||
current_id = queue.pop(0)
|
||||
result.append(test_case_map[current_id])
|
||||
|
||||
for dependent_id in self._reverse_dependency_map[current_id]:
|
||||
in_degree[dependent_id] -= 1
|
||||
if in_degree[dependent_id] == 0:
|
||||
queue.append(dependent_id)
|
||||
|
||||
if len(result) != len(test_cases):
|
||||
raise TestRunException("存在循环依赖,无法确定测试用例执行顺序")
|
||||
|
||||
return result
|
||||
|
||||
def _prepare_request_data(self, test_case: TestCase) -> Dict[str, Any]:
|
||||
"""准备请求数据
|
||||
|
||||
Args:
|
||||
test_case: 测试用例
|
||||
|
||||
Returns:
|
||||
准备好的请求数据
|
||||
"""
|
||||
params = test_case.params.copy() if test_case.params else {}
|
||||
body = test_case.body.copy() if test_case.body else {}
|
||||
|
||||
params = self._resolve_context_variables(params)
|
||||
body = self._resolve_context_variables(body)
|
||||
|
||||
return {"params": params, "body": body}
|
||||
|
||||
def _resolve_context_variables(self, data: Any) -> Any:
|
||||
"""解析上下文变量
|
||||
|
||||
Args:
|
||||
data: 数据
|
||||
|
||||
Returns:
|
||||
解析后的数据
|
||||
"""
|
||||
if isinstance(data, str):
|
||||
if data.startswith("${") and data.endswith("}"):
|
||||
var_name = data[2:-1]
|
||||
return self.get_context(var_name, data)
|
||||
return data
|
||||
elif isinstance(data, dict):
|
||||
return {k: self._resolve_context_variables(v) for k, v in data.items()}
|
||||
elif isinstance(data, list):
|
||||
return [self._resolve_context_variables(item) for item in data]
|
||||
else:
|
||||
return data
|
||||
|
||||
def _execute_setup(self, test_case: TestCase):
|
||||
"""执行前置操作
|
||||
|
||||
Args:
|
||||
test_case: 测试用例
|
||||
"""
|
||||
if not test_case.setup:
|
||||
return
|
||||
|
||||
setup_type = test_case.setup.get("type")
|
||||
|
||||
if setup_type == "set_context":
|
||||
key = test_case.setup.get("key")
|
||||
value = test_case.setup.get("value")
|
||||
self.set_context(key, value)
|
||||
elif setup_type == "sleep":
|
||||
import time
|
||||
time.sleep(test_case.setup.get("seconds", 1))
|
||||
|
||||
def _execute_teardown(self, test_case: TestCase):
|
||||
"""执行后置操作
|
||||
|
||||
Args:
|
||||
test_case: 测试用例
|
||||
"""
|
||||
if not test_case.teardown:
|
||||
return
|
||||
|
||||
teardown_type = test_case.teardown.get("type")
|
||||
|
||||
if teardown_type == "clear_context":
|
||||
key = test_case.teardown.get("key")
|
||||
if key in self._context:
|
||||
del self._context[key]
|
||||
elif teardown_type == "sleep":
|
||||
import time
|
||||
time.sleep(test_case.teardown.get("seconds", 1))
|
||||
|
||||
def _execute_test_case(self, test_case: TestCase) -> TestResult:
|
||||
"""执行单个测试用例
|
||||
|
||||
Args:
|
||||
test_case: 测试用例
|
||||
|
||||
Returns:
|
||||
测试结果
|
||||
"""
|
||||
if self.logger:
|
||||
self.logger.info(f"执行测试用例: {test_case.name} ({test_case.id})")
|
||||
|
||||
try:
|
||||
self._execute_setup(test_case)
|
||||
|
||||
request_data = self._prepare_request_data(test_case)
|
||||
|
||||
headers = test_case.headers.copy() if test_case.headers else {}
|
||||
|
||||
if test_case.auth_required and self.auth_manager:
|
||||
auth_headers = self.auth_manager.get_auth_headers()
|
||||
headers.update(auth_headers)
|
||||
|
||||
response_data = self.api_client.request(
|
||||
method=test_case.method,
|
||||
endpoint=test_case.endpoint,
|
||||
headers=headers,
|
||||
params=request_data.get("params"),
|
||||
body=request_data.get("body"),
|
||||
retry_count=test_case.retry_count
|
||||
)
|
||||
|
||||
status_code = response_data["status_code"]
|
||||
response_body = response_data["response_body"]
|
||||
response_headers = response_data["response_headers"]
|
||||
performance = response_data["performance"]
|
||||
|
||||
passed, error_message = self.validation_engine.validate_response(
|
||||
test_case,
|
||||
status_code,
|
||||
response_body,
|
||||
response_headers
|
||||
)
|
||||
|
||||
if passed and test_case.validations:
|
||||
self._extract_response_data(test_case, response_body)
|
||||
|
||||
test_result = TestResult(
|
||||
test_case=test_case,
|
||||
passed=passed,
|
||||
status_code=status_code,
|
||||
response_body=response_body,
|
||||
response_headers=response_headers,
|
||||
error_message=error_message if not passed else None,
|
||||
performance=performance,
|
||||
execution_time=performance.response_time / 1000.0,
|
||||
retry_count=test_case.retry_count
|
||||
)
|
||||
|
||||
self._execute_teardown(test_case)
|
||||
|
||||
if self.logger:
|
||||
if passed:
|
||||
self.logger.info(f"测试用例通过: {test_case.name}")
|
||||
else:
|
||||
self.logger.error(f"测试用例失败: {test_case.name} - {error_message}")
|
||||
|
||||
return test_result
|
||||
|
||||
except RequestException as e:
|
||||
if self.logger:
|
||||
self.logger.error(f"请求异常: {test_case.name} - {str(e)}")
|
||||
|
||||
return TestResult(
|
||||
test_case=test_case,
|
||||
passed=False,
|
||||
status_code=0,
|
||||
response_body=None,
|
||||
response_headers={},
|
||||
error_message=f"请求异常: {str(e)}"
|
||||
)
|
||||
except Exception as e:
|
||||
if self.logger:
|
||||
self.logger.error(f"执行异常: {test_case.name} - {str(e)}")
|
||||
|
||||
return TestResult(
|
||||
test_case=test_case,
|
||||
passed=False,
|
||||
status_code=0,
|
||||
response_body=None,
|
||||
response_headers={},
|
||||
error_message=f"执行异常: {str(e)}"
|
||||
)
|
||||
|
||||
def _extract_response_data(self, test_case: TestCase, response_body: Any):
|
||||
"""提取响应数据到上下文
|
||||
|
||||
Args:
|
||||
test_case: 测试用例
|
||||
response_body: 响应体
|
||||
"""
|
||||
extract_config = test_case.validations or []
|
||||
|
||||
for validation in extract_config:
|
||||
if validation.get("type") == "extract":
|
||||
field = validation.get("field")
|
||||
var_name = validation.get("var_name", field)
|
||||
|
||||
if isinstance(response_body, dict) and field in response_body:
|
||||
self.set_context(var_name, response_body[field])
|
||||
|
||||
def execute_test_suite(
|
||||
self,
|
||||
test_cases: List[TestCase],
|
||||
stop_on_failure: bool = False
|
||||
) -> TestSuiteResult:
|
||||
"""执行测试套件
|
||||
|
||||
Args:
|
||||
test_cases: 测试用例列表
|
||||
stop_on_failure: 是否在失败时停止
|
||||
|
||||
Returns:
|
||||
测试套件结果
|
||||
"""
|
||||
if self.logger:
|
||||
self.logger.info(f"开始执行测试套件,共 {len(test_cases)} 个测试用例")
|
||||
|
||||
self._context.clear()
|
||||
|
||||
sorted_test_cases = self._topological_sort(test_cases)
|
||||
|
||||
results = []
|
||||
|
||||
for test_case in sorted_test_cases:
|
||||
if not test_case.enabled:
|
||||
if self.logger:
|
||||
self.logger.info(f"跳过已禁用的测试用例: {test_case.name}")
|
||||
continue
|
||||
|
||||
result = self._execute_test_case(test_case)
|
||||
results.append(result)
|
||||
|
||||
if not result.passed and stop_on_failure:
|
||||
if self.logger:
|
||||
self.logger.warning(f"测试失败,停止执行: {test_case.name}")
|
||||
break
|
||||
|
||||
passed_count = sum(1 for r in results if r.passed)
|
||||
failed_count = sum(1 for r in results if not r.passed)
|
||||
skipped_count = len(test_cases) - len(results)
|
||||
|
||||
test_suite_result = TestSuiteResult(
|
||||
suite_name="Test Suite",
|
||||
total=len(test_cases),
|
||||
passed=passed_count,
|
||||
failed=failed_count,
|
||||
skipped=skipped_count,
|
||||
results=results,
|
||||
start_time=datetime.now()
|
||||
)
|
||||
|
||||
if self.logger:
|
||||
self.logger.info(
|
||||
f"测试套件执行完成: 通过 {test_suite_result.passed}, "
|
||||
f"失败 {test_suite_result.failed}, "
|
||||
f"跳过 {test_suite_result.skipped}"
|
||||
)
|
||||
|
||||
return test_suite_result
|
||||
|
||||
def execute_test_cases_by_filter(
|
||||
self,
|
||||
test_cases: List[TestCase],
|
||||
module_filter: Optional[str] = None,
|
||||
tag_filter: Optional[List[str]] = None,
|
||||
priority_filter: Optional[int] = None
|
||||
) -> TestSuiteResult:
|
||||
"""按过滤条件执行测试用例
|
||||
|
||||
Args:
|
||||
test_cases: 测试用例列表
|
||||
module_filter: 模块过滤
|
||||
tag_filter: 标签过滤
|
||||
priority_filter: 优先级过滤
|
||||
|
||||
Returns:
|
||||
测试套件结果
|
||||
"""
|
||||
filtered_cases = []
|
||||
|
||||
for test_case in test_cases:
|
||||
if module_filter and test_case.module != module_filter:
|
||||
continue
|
||||
|
||||
if tag_filter and not any(tag in test_case.tags for tag in tag_filter):
|
||||
continue
|
||||
|
||||
if priority_filter is not None and test_case.priority != priority_filter:
|
||||
continue
|
||||
|
||||
filtered_cases.append(test_case)
|
||||
|
||||
if self.logger:
|
||||
self.logger.info(f"过滤后执行 {len(filtered_cases)} 个测试用例")
|
||||
|
||||
return self.execute_test_suite(filtered_cases)
|
||||
@@ -0,0 +1,337 @@
|
||||
from typing import Dict, Any, List
|
||||
import json
|
||||
import re
|
||||
from apitest.models.test_models import TestCase, TestResult, PerformanceMetrics
|
||||
from apitest.models.exceptions import ValidationException
|
||||
|
||||
|
||||
class ValidationEngine:
|
||||
"""验证引擎"""
|
||||
|
||||
def __init__(self, logger=None):
|
||||
"""初始化验证引擎
|
||||
|
||||
Args:
|
||||
logger: 日志记录器
|
||||
"""
|
||||
self.logger = logger
|
||||
|
||||
def validate_response(
|
||||
self,
|
||||
test_case: TestCase,
|
||||
status_code: int,
|
||||
response_body: Any,
|
||||
response_headers: Dict[str, str]
|
||||
) -> tuple[bool, str]:
|
||||
"""验证响应
|
||||
|
||||
Args:
|
||||
test_case: 测试用例
|
||||
status_code: HTTP状态码
|
||||
response_body: 响应体
|
||||
response_headers: 响应头
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
if not test_case.validations:
|
||||
return True, ""
|
||||
|
||||
for validation in test_case.validations:
|
||||
passed, error = self._execute_validation(
|
||||
validation,
|
||||
status_code,
|
||||
response_body,
|
||||
response_headers
|
||||
)
|
||||
|
||||
if not passed:
|
||||
return False, error
|
||||
|
||||
return True, ""
|
||||
|
||||
def _execute_validation(
|
||||
self,
|
||||
validation: Dict[str, Any],
|
||||
status_code: int,
|
||||
response_body: Any,
|
||||
response_headers: Dict[str, str]
|
||||
) -> tuple[bool, str]:
|
||||
"""执行单个验证规则
|
||||
|
||||
Args:
|
||||
validation: 验证规则
|
||||
status_code: HTTP状态码
|
||||
response_body: 响应体
|
||||
response_headers: 响应头
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
validation_type = validation.get("type")
|
||||
|
||||
if validation_type == "status_code":
|
||||
return self._validate_status_code(validation, status_code)
|
||||
elif validation_type == "contains":
|
||||
return self._validate_contains(validation, response_body)
|
||||
elif validation_type == "equals":
|
||||
return self._validate_equals(validation, response_body)
|
||||
elif validation_type == "json_path":
|
||||
return self._validate_json_path(validation, response_body)
|
||||
elif validation_type == "regex":
|
||||
return self._validate_regex(validation, response_body)
|
||||
elif validation_type == "header":
|
||||
return self._validate_header(validation, response_headers)
|
||||
elif validation_type == "response_time":
|
||||
return self._validate_response_time(validation)
|
||||
elif validation_type == "schema":
|
||||
return self._validate_schema(validation, response_body)
|
||||
else:
|
||||
return False, f"不支持的验证类型: {validation_type}"
|
||||
|
||||
def _validate_status_code(self, validation: Dict[str, Any], status_code: int) -> tuple[bool, str]:
|
||||
"""验证状态码
|
||||
|
||||
Args:
|
||||
validation: 验证规则
|
||||
status_code: HTTP状态码
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
expected_code = validation.get("value")
|
||||
if status_code == expected_code:
|
||||
return True, ""
|
||||
|
||||
return False, f"状态码验证失败: 期望 {expected_code}, 实际 {status_code}"
|
||||
|
||||
def _validate_contains(self, validation: Dict[str, Any], response_body: Any) -> tuple[bool, str]:
|
||||
"""验证响应体包含指定内容
|
||||
|
||||
Args:
|
||||
validation: 验证规则
|
||||
response_body: 响应体
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
expected_value = validation.get("value")
|
||||
field = validation.get("field")
|
||||
|
||||
if field:
|
||||
if isinstance(response_body, dict):
|
||||
actual_value = response_body.get(field)
|
||||
else:
|
||||
return False, f"响应体不是字典类型,无法访问字段: {field}"
|
||||
else:
|
||||
actual_value = response_body
|
||||
|
||||
if str(expected_value) in str(actual_value):
|
||||
return True, ""
|
||||
|
||||
return False, f"包含验证失败: 响应体中未找到 '{expected_value}'"
|
||||
|
||||
def _validate_equals(self, validation: Dict[str, Any], response_body: Any) -> tuple[bool, str]:
|
||||
"""验证响应体等于指定值
|
||||
|
||||
Args:
|
||||
validation: 验证规则
|
||||
response_body: 响应体
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
expected_value = validation.get("value")
|
||||
field = validation.get("field")
|
||||
|
||||
if field:
|
||||
if isinstance(response_body, dict):
|
||||
actual_value = response_body.get(field)
|
||||
else:
|
||||
return False, f"响应体不是字典类型,无法访问字段: {field}"
|
||||
else:
|
||||
actual_value = response_body
|
||||
|
||||
if actual_value == expected_value:
|
||||
return True, ""
|
||||
|
||||
return False, f"相等验证失败: 期望 {expected_value}, 实际 {actual_value}"
|
||||
|
||||
def _validate_json_path(self, validation: Dict[str, Any], response_body: Any) -> tuple[bool, str]:
|
||||
"""验证JSON路径
|
||||
|
||||
Args:
|
||||
validation: 验证规则
|
||||
response_body: 响应体
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
path = validation.get("path")
|
||||
expected_value = validation.get("value")
|
||||
|
||||
try:
|
||||
actual_value = self._get_json_path_value(response_body, path)
|
||||
|
||||
if actual_value == expected_value:
|
||||
return True, ""
|
||||
|
||||
return False, f"JSON路径验证失败: {path} 期望 {expected_value}, 实际 {actual_value}"
|
||||
|
||||
except (KeyError, IndexError, TypeError) as e:
|
||||
return False, f"JSON路径访问失败: {path} - {str(e)}"
|
||||
|
||||
def _get_json_path_value(self, data: Any, path: str) -> Any:
|
||||
"""获取JSON路径值
|
||||
|
||||
Args:
|
||||
data: 数据
|
||||
path: JSON路径
|
||||
|
||||
Returns:
|
||||
路径对应的值
|
||||
"""
|
||||
parts = path.split(".")
|
||||
current = data
|
||||
|
||||
for part in parts:
|
||||
if isinstance(current, dict):
|
||||
current = current[part]
|
||||
elif isinstance(current, list) and part.isdigit():
|
||||
current = current[int(part)]
|
||||
else:
|
||||
raise KeyError(f"无法访问路径: {part}")
|
||||
|
||||
return current
|
||||
|
||||
def _validate_regex(self, validation: Dict[str, Any], response_body: Any) -> tuple[bool, str]:
|
||||
"""验证正则表达式
|
||||
|
||||
Args:
|
||||
validation: 验证规则
|
||||
response_body: 响应体
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
pattern = validation.get("pattern")
|
||||
field = validation.get("field")
|
||||
|
||||
if field:
|
||||
if isinstance(response_body, dict):
|
||||
actual_value = str(response_body.get(field, ""))
|
||||
else:
|
||||
actual_value = str(response_body)
|
||||
else:
|
||||
actual_value = str(response_body)
|
||||
|
||||
if re.search(pattern, actual_value):
|
||||
return True, ""
|
||||
|
||||
return False, f"正则表达式验证失败: '{actual_value}' 不匹配模式 '{pattern}'"
|
||||
|
||||
def _validate_header(self, validation: Dict[str, Any], response_headers: Dict[str, str]) -> tuple[bool, str]:
|
||||
"""验证响应头
|
||||
|
||||
Args:
|
||||
validation: 验证规则
|
||||
response_headers: 响应头
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
header_name = validation.get("name")
|
||||
expected_value = validation.get("value")
|
||||
|
||||
actual_value = response_headers.get(header_name)
|
||||
|
||||
if actual_value is None:
|
||||
return False, f"响应头中未找到: {header_name}"
|
||||
|
||||
if expected_value and actual_value != expected_value:
|
||||
return False, f"响应头验证失败: {header_name} 期望 {expected_value}, 实际 {actual_value}"
|
||||
|
||||
return True, ""
|
||||
|
||||
def _validate_response_time(self, validation: Dict[str, Any]) -> tuple[bool, str]:
|
||||
"""验证响应时间(需要在TestResult中检查)
|
||||
|
||||
Args:
|
||||
validation: 验证规则
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
max_time = validation.get("max_time")
|
||||
|
||||
return True, ""
|
||||
|
||||
def _validate_schema(self, validation: Dict[str, Any], response_body: Any) -> tuple[bool, str]:
|
||||
"""验证响应体结构
|
||||
|
||||
Args:
|
||||
validation: 验证规则
|
||||
response_body: 响应体
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
schema = validation.get("schema")
|
||||
|
||||
if not isinstance(response_body, dict):
|
||||
return False, f"响应体不是字典类型,无法验证结构"
|
||||
|
||||
for field, field_type in schema.items():
|
||||
if field not in response_body:
|
||||
return False, f"响应体中缺少字段: {field}"
|
||||
|
||||
actual_type = type(response_body[field]).__name__
|
||||
expected_type = field_type
|
||||
|
||||
if actual_type != expected_type:
|
||||
return False, f"字段 {field} 类型错误: 期望 {expected_type}, 实际 {actual_type}"
|
||||
|
||||
return True, ""
|
||||
|
||||
def validate_performance(
|
||||
self,
|
||||
performance: PerformanceMetrics,
|
||||
max_response_time: int
|
||||
) -> tuple[bool, str]:
|
||||
"""验证性能指标
|
||||
|
||||
Args:
|
||||
performance: 性能指标
|
||||
max_response_time: 最大响应时间(毫秒)
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
if performance.response_time > max_response_time:
|
||||
return False, f"响应时间超过阈值: {performance.response_time}ms > {max_response_time}ms"
|
||||
|
||||
return True, ""
|
||||
|
||||
def validate_test_result(
|
||||
self,
|
||||
test_result: TestResult,
|
||||
max_response_time: int
|
||||
) -> tuple[bool, str]:
|
||||
"""验证测试结果
|
||||
|
||||
Args:
|
||||
test_result: 测试结果
|
||||
max_response_time: 最大响应时间(毫秒)
|
||||
|
||||
Returns:
|
||||
(是否通过, 错误消息)
|
||||
"""
|
||||
if not test_result.passed:
|
||||
return False, test_result.error_message or "测试失败"
|
||||
|
||||
if test_result.performance:
|
||||
passed, error = self.validate_performance(test_result.performance, max_response_time)
|
||||
if not passed:
|
||||
return False, error
|
||||
|
||||
return True, ""
|
||||
Reference in New Issue
Block a user