Files
张翔 08ea5fbe98 feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
2026-03-28 14:37:29 +08:00

655 lines
15 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
统一测试工具接口标准
定义所有测试工具应遵循的统一接口规范
"""
from abc import ABC, abstractmethod
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass
from enum import Enum
class TestStatus(Enum):
"""测试状态枚举"""
PASSED = "passed"
FAILED = "failed"
SKIPPED = "skipped"
RUNNING = "running"
class LogLevel(Enum):
"""日志级别枚举"""
DEBUG = "DEBUG"
INFO = "INFO"
WARNING = "WARNING"
ERROR = "ERROR"
CRITICAL = "CRITICAL"
@dataclass
class TestConfig:
"""测试配置数据类"""
name: str
version: str
description: str
# API配置
api_base_url: str
api_timeout: int
api_max_retries: int
# 认证配置
auth_enabled: bool
auth_login_endpoint: str
auth_username: str
auth_password: str
# 测试配置
test_parallel: bool
test_retry_count: int
# 报告配置
report_output_dir: str
report_formats: List[str]
report_include_details: bool
# 日志配置
logging_level: str
logging_file: str
logging_console: bool
@dataclass
class TestResult:
"""测试结果数据类"""
test_name: str
test_type: str
status: TestStatus
url: str
method: str
status_code: int
response_time: float
error_message: str
request_data: Dict[str, Any]
response_data: Dict[str, Any]
timestamp: str
stack_trace: Optional[str] = None
def to_dict(self) -> Dict[str, Any]:
"""转换为字典"""
return {
"test_name": self.test_name,
"test_type": self.test_type,
"status": self.status.value,
"url": self.url,
"method": self.method,
"status_code": self.status_code,
"response_time": self.response_time,
"error_message": self.error_message,
"request_data": self.request_data,
"response_data": self.response_data,
"timestamp": self.timestamp,
"stack_trace": self.stack_trace
}
@dataclass
class TestSummary:
"""测试摘要数据类"""
total: int
passed: int
failed: int
skipped: int
pass_rate: float
total_time: float
start_time: str
end_time: str
def to_dict(self) -> Dict[str, Any]:
"""转换为字典"""
return {
"total": self.total,
"passed": self.passed,
"failed": self.failed,
"skipped": self.skipped,
"pass_rate": self.pass_rate,
"total_time": self.total_time,
"start_time": self.start_time,
"end_time": self.end_time
}
@dataclass
class ValidationRule:
"""验证规则数据类"""
rule_type: str
expected_value: Any
path: Optional[str] = None
description: Optional[str] = None
class ITestTool(ABC):
"""测试工具接口"""
@abstractmethod
def get_name(self) -> str:
"""
获取测试工具名称
Returns:
工具名称
"""
pass
@abstractmethod
def get_version(self) -> str:
"""
获取测试工具版本
Returns:
工具版本
"""
pass
@abstractmethod
def load_config(self, config_path: str = None) -> None:
"""
加载配置
Args:
config_path: 配置文件路径
"""
pass
@abstractmethod
def get_config(self) -> TestConfig:
"""
获取配置
Returns:
配置对象
"""
pass
@abstractmethod
def run_tests(self, test_cases: List[Any] = None) -> Tuple[List[TestResult], TestSummary]:
"""
运行测试
Args:
test_cases: 测试用例列表
Returns:
(测试结果列表, 测试摘要)
"""
pass
@abstractmethod
def generate_report(self, results: List[TestResult], summary: TestSummary, format: str = "json") -> str:
"""
生成测试报告
Args:
results: 测试结果列表
summary: 测试摘要
format: 报告格式(json, html, pdf
Returns:
报告文件路径
"""
pass
@abstractmethod
def set_log_level(self, level: LogLevel) -> None:
"""
设置日志级别
Args:
level: 日志级别
"""
pass
@abstractmethod
def get_logs(self) -> List[str]:
"""
获取日志
Returns:
日志列表
"""
pass
@abstractmethod
def cleanup(self) -> None:
"""清理资源"""
pass
class IAPITester(ITestTool):
"""API测试工具接口"""
@abstractmethod
def login(self, username: str = None, password: str = None) -> bool:
"""
用户登录
Args:
username: 用户名
password: 密码
Returns:
是否登录成功
"""
pass
@abstractmethod
def request(
self,
method: str,
endpoint: str,
data: Dict[str, Any] = None,
params: Dict[str, Any] = None,
headers: Dict[str, str] = None,
expected_status: int = 200
) -> TestResult:
"""
发送HTTP请求
Args:
method: HTTP方法
endpoint: API端点
data: 请求体数据
params: URL参数
headers: 请求头
expected_status: 期望的状态码
Returns:
测试结果
"""
pass
@abstractmethod
def validate(self, result: TestResult, rules: List[ValidationRule]) -> TestResult:
"""
验证测试结果
Args:
result: 测试结果
rules: 验证规则列表
Returns:
验证后的测试结果
"""
pass
class IE2ETester(ITestTool):
"""E2E测试工具接口"""
@abstractmethod
def navigate(self, url: str) -> None:
"""
导航到指定URL
Args:
url: 目标URL
"""
pass
@abstractmethod
def click(self, selector: str) -> None:
"""
点击元素
Args:
selector: 元素选择器
"""
pass
@abstractmethod
def fill(self, selector: str, value: str) -> None:
"""
填写表单字段
Args:
selector: 元素选择器
value: 填充值
"""
pass
@abstractmethod
def wait_for_element(self, selector: str, timeout: int = 5000) -> None:
"""
等待元素出现
Args:
selector: 元素选择器
timeout: 超时时间(毫秒)
"""
pass
@abstractmethod
def take_screenshot(self, name: str) -> str:
"""
截取屏幕截图
Args:
name: 截图名称
Returns:
截图文件路径
"""
pass
@abstractmethod
def expect_visible(self, selector: str, timeout: int = 5000) -> None:
"""
期望元素可见
Args:
selector: 元素选择器
timeout: 超时时间(毫秒)
"""
pass
@abstractmethod
def expect_text(self, selector: str, expected_text: str, timeout: int = 5000) -> None:
"""
期望元素包含指定文本
Args:
selector: 元素选择器
expected_text: 期望的文本
timeout: 超时时间(毫秒)
"""
pass
class IValidationEngine(ABC):
"""验证引擎接口"""
@abstractmethod
def validate_status_code(self, expected: int, actual: int) -> Tuple[bool, str]:
"""
验证HTTP状态码
Args:
expected: 期望的状态码
actual: 实际的状态码
Returns:
(是否通过, 错误消息)
"""
pass
@abstractmethod
def validate_response_body(self, expected: Dict[str, Any], actual: Dict[str, Any]) -> Tuple[bool, str]:
"""
验证响应体
Args:
expected: 期望的响应体
actual: 实际的响应体
Returns:
(是否通过, 错误消息)
"""
pass
@abstractmethod
def validate_contains(self, expected_value: Any, actual_value: Any) -> Tuple[bool, str]:
"""
验证包含关系
Args:
expected_value: 期望包含的值
actual_value: 实际的值
Returns:
(是否通过, 错误消息)
"""
pass
@abstractmethod
def validate_equals(self, expected_value: Any, actual_value: Any) -> Tuple[bool, str]:
"""
验证相等关系
Args:
expected_value: 期望的值
actual_value: 实际的值
Returns:
(是否通过, 错误消息)
"""
pass
@abstractmethod
def validate_json_path(self, path: str, expected_value: Any, actual_data: Dict[str, Any]) -> Tuple[bool, str]:
"""
验证JSON路径
Args:
path: JSON路径
expected_value: 期望的值
actual_data: 实际的数据
Returns:
(是否通过, 错误消息)
"""
pass
@abstractmethod
def validate_regex(self, pattern: str, actual_value: str) -> Tuple[bool, str]:
"""
验证正则表达式
Args:
pattern: 正则表达式模式
actual_value: 实际的值
Returns:
(是否通过, 错误消息)
"""
pass
@abstractmethod
def validate_header(self, expected_header: Dict[str, str], actual_headers: Dict[str, str]) -> Tuple[bool, str]:
"""
验证响应头
Args:
expected_header: 期望的响应头
actual_headers: 实际的响应头
Returns:
(是否通过, 错误消息)
"""
pass
@abstractmethod
def validate_response_time(self, expected_max_time: float, actual_time: float) -> Tuple[bool, str]:
"""
验证响应时间
Args:
expected_max_time: 期望的最大响应时间(毫秒)
actual_time: 实际的响应时间(毫秒)
Returns:
(是否通过, 错误消息)
"""
pass
@abstractmethod
def validate_schema(self, expected_schema: Dict[str, Any], actual_data: Dict[str, Any]) -> Tuple[bool, str]:
"""
验证数据结构
Args:
expected_schema: 期望的结构
actual_data: 实际的数据
Returns:
(是否通过, 错误消息)
"""
pass
class IReportGenerator(ABC):
"""报告生成器接口"""
@abstractmethod
def generate_json_report(self, results: List[TestResult], summary: TestSummary, filename: str = None) -> str:
"""
生成JSON格式报告
Args:
results: 测试结果列表
summary: 测试摘要
filename: 报告文件名
Returns:
报告文件路径
"""
pass
@abstractmethod
def generate_html_report(self, results: List[TestResult], summary: TestSummary, filename: str = None) -> str:
"""
生成HTML格式报告
Args:
results: 测试结果列表
summary: 测试摘要
filename: 报告文件名
Returns:
报告文件路径
"""
pass
@abstractmethod
def generate_pdf_report(self, results: List[TestResult], summary: TestSummary, filename: str = None) -> str:
"""
生成PDF格式报告
Args:
results: 测试结果列表
summary: 测试摘要
filename: 报告文件名
Returns:
报告文件路径
"""
pass
class ILogger(ABC):
"""日志记录器接口"""
@abstractmethod
def debug(self, message: str) -> None:
"""记录调试信息"""
pass
@abstractmethod
def info(self, message: str) -> None:
"""记录信息"""
pass
@abstractmethod
def warning(self, message: str) -> None:
"""记录警告"""
pass
@abstractmethod
def error(self, message: str) -> None:
"""记录错误"""
pass
@abstractmethod
def critical(self, message: str) -> None:
"""记录严重错误"""
pass
@abstractmethod
def exception(self, message: str) -> None:
"""记录异常信息"""
pass
@abstractmethod
def set_level(self, level: LogLevel) -> None:
"""
设置日志级别
Args:
level: 日志级别
"""
pass
@abstractmethod
def get_logs(self) -> List[str]:
"""
获取日志
Returns:
日志列表
"""
pass
class ITestDataGenerator(ABC):
"""测试数据生成器接口"""
@abstractmethod
def generate_user_data(self, overrides: Dict[str, Any] = None) -> Dict[str, Any]:
"""
生成用户数据
Args:
overrides: 覆盖的默认值
Returns:
用户数据
"""
pass
@abstractmethod
def generate_role_data(self, overrides: Dict[str, Any] = None) -> Dict[str, Any]:
"""
生成角色数据
Args:
overrides: 覆盖的默认值
Returns:
角色数据
"""
pass
@abstractmethod
def generate_menu_data(self, overrides: Dict[str, Any] = None) -> Dict[str, Any]:
"""
生成菜单数据
Args:
overrides: 覆盖的默认值
Returns:
菜单数据
"""
pass
@abstractmethod
def generate_permission_data(self, overrides: Dict[str, Any] = None) -> Dict[str, Any]:
"""
生成权限数据
Args:
overrides: 覆盖的默认值
Returns:
权限数据
"""
pass