""" 测试验证引擎模块 """ from typing import Dict, Any, Tuple, Optional import re import json from datetime import datetime class ValidationEngine: """测试验证引擎""" @staticmethod def validate_status_code(expected: int, actual: int) -> Tuple[bool, str]: """ 验证HTTP状态码 Args: expected: 期望的状态码 actual: 实际的状态码 Returns: (是否通过, 错误消息) """ if expected == actual: return True, "" return False, f"期望状态码{expected},实际{actual}" @staticmethod def validate_response_body(expected: Dict[str, Any], actual: Dict[str, Any]) -> Tuple[bool, str]: """ 验证响应体 Args: expected: 期望的响应体 actual: 实际的响应体 Returns: (是否通过, 错误消息) """ if expected == actual: return True, "" # 找出差异 differences = ValidationEngine._find_differences(expected, actual) return False, f"响应体不匹配: {differences}" @staticmethod def validate_contains(expected_value: Any, actual_value: Any) -> Tuple[bool, str]: """ 验证包含关系 Args: expected_value: 期望包含的值 actual_value: 实际值 Returns: (是否通过, 错误消息) """ if isinstance(actual_value, (str, list, dict)): if expected_value in actual_value: return True, "" return False, f"期望值'{expected_value}'不在实际值中" if expected_value == actual_value: return True, "" return False, f"期望包含'{expected_value}',实际为'{actual_value}'" @staticmethod def validate_equals(expected_value: Any, actual_value: Any) -> Tuple[bool, str]: """ 验证相等关系 Args: expected_value: 期望的值 actual_value: 实际的值 Returns: (是否通过, 错误消息) """ if expected_value == actual_value: return True, "" return False, f"期望值'{expected_value}',实际值'{actual_value}'" @staticmethod def validate_json_path(path: str, expected_value: Any, actual_data: Dict[str, Any]) -> Tuple[bool, str]: """ 验证JSON路径 Args: path: JSON路径(如"data.user.id") expected_value: 期望的值 actual_data: 实际的数据 Returns: (是否通过, 错误消息) """ try: keys = path.split('.') value = actual_data for key in keys: if isinstance(value, dict): value = value.get(key) elif isinstance(value, list) and key.isdigit(): value = value[int(key)] else: return False, f"路径'{path}'不存在" if value == expected_value: return True, "" return False, f"路径'{path}'期望值'{expected_value}',实际值'{value}'" except Exception as e: return False, f"验证JSON路径失败: {str(e)}" @staticmethod def validate_regex(pattern: str, actual_value: str) -> Tuple[bool, str]: """ 验证正则表达式 Args: pattern: 正则表达式模式 actual_value: 实际的值 Returns: (是否通过, 错误消息) """ try: if re.match(pattern, str(actual_value)): return True, "" return False, f"值'{actual_value}'不匹配正则表达式'{pattern}'" except Exception as e: return False, f"正则表达式验证失败: {str(e)}" @staticmethod def validate_header(expected_header: Dict[str, str], actual_headers: Dict[str, str]) -> Tuple[bool, str]: """ 验证响应头 Args: expected_header: 期望的响应头 actual_headers: 实际的响应头 Returns: (是否通过, 错误消息) """ for key, expected_value in expected_header.items(): actual_value = actual_headers.get(key) if actual_value is None: return False, f"缺少响应头: {key}" if actual_value != expected_value: return False, f"响应头'{key}'期望值'{expected_value}',实际值'{actual_value}'" return True, "" @staticmethod def validate_response_time(expected_max_time: float, actual_time: float) -> Tuple[bool, str]: """ 验证响应时间 Args: expected_max_time: 期望的最大响应时间(毫秒) actual_time: 实际的响应时间(毫秒) Returns: (是否通过, 错误消息) """ if actual_time <= expected_max_time: return True, "" return False, f"响应时间{actual_time}ms超过期望最大值{expected_max_time}ms" @staticmethod def validate_schema(expected_schema: Dict[str, Any], actual_data: Dict[str, Any]) -> Tuple[bool, str]: """ 验证数据结构 Args: expected_schema: 期望的结构(简化版) actual_data: 实际的数据 Returns: (是否通过, 错误消息) """ for key, expected_type in expected_schema.items(): if key not in actual_data: return False, f"缺少字段: {key}" actual_value = actual_data[key] if expected_type == "string" and not isinstance(actual_value, str): return False, f"字段'{key}'期望类型string,实际类型{type(actual_value).__name__}" elif expected_type == "number" and not isinstance(actual_value, (int, float)): return False, f"字段'{key}'期望类型number,实际类型{type(actual_value).__name__}" elif expected_type == "boolean" and not isinstance(actual_value, bool): return False, f"字段'{key}'期望类型boolean,实际类型{type(actual_value).__name__}" elif expected_type == "array" and not isinstance(actual_value, list): return False, f"字段'{key}'期望类型array,实际类型{type(actual_value).__name__}" elif expected_type == "object" and not isinstance(actual_value, dict): return False, f"字段'{key}'期望类型object,实际类型{type(actual_value).__name__}" return True, "" @staticmethod def _find_differences(expected: Any, actual: Any, path: str = "") -> str: """ 找出两个值之间的差异 Args: expected: 期望的值 actual: 实际的值 path: 当前路径 Returns: 差异描述 """ if expected == actual: return "" if isinstance(expected, dict) and isinstance(actual, dict): differences = [] all_keys = set(expected.keys()) | set(actual.keys()) for key in all_keys: new_path = f"{path}.{key}" if path else key if key not in expected: differences.append(f"{new_path}: 实际存在但期望不存在") elif key not in actual: differences.append(f"{new_path}: 期望存在但实际不存在") else: diff = ValidationEngine._find_differences(expected[key], actual[key], new_path) if diff: differences.append(diff) return "; ".join(differences) elif isinstance(expected, list) and isinstance(actual, list): if len(expected) != len(actual): return f"{path}: 长度不匹配(期望{len(expected)},实际{len(actual)})" differences = [] for i, (exp_item, act_item) in enumerate(zip(expected, actual)): new_path = f"{path}[{i}]" diff = ValidationEngine._find_differences(exp_item, act_item, new_path) if diff: differences.append(diff) return "; ".join(differences) else: return f"{path}: 期望'{expected}',实际'{actual}'" class ValidationRule: """验证规则""" def __init__(self, rule_type: str, expected_value: Any = None, path: str = None): """ 初始化验证规则 Args: rule_type: 规则类型(status_code, contains, equals, json_path, regex, header, response_time, schema) expected_value: 期望值 path: JSON路径(仅用于json_path规则) """ self.rule_type = rule_type self.expected_value = expected_value self.path = path def validate(self, actual_value: Any = None, actual_data: Dict[str, Any] = None) -> Tuple[bool, str]: """ 执行验证 Args: actual_value: 实际值 actual_data: 实际数据(用于JSON路径验证) Returns: (是否通过, 错误消息) """ if self.rule_type == "status_code": return ValidationEngine.validate_status_code(self.expected_value, actual_value) elif self.rule_type == "contains": return ValidationEngine.validate_contains(self.expected_value, actual_value) elif self.rule_type == "equals": return ValidationEngine.validate_equals(self.expected_value, actual_value) elif self.rule_type == "json_path": return ValidationEngine.validate_json_path(self.path, self.expected_value, actual_data) elif self.rule_type == "regex": return ValidationEngine.validate_regex(self.expected_value, actual_value) elif self.rule_type == "header": return ValidationEngine.validate_header(self.expected_value, actual_value) elif self.rule_type == "response_time": return ValidationEngine.validate_response_time(self.expected_value, actual_value) elif self.rule_type == "schema": return ValidationEngine.validate_schema(self.expected_value, actual_data) else: return False, f"未知的验证规则类型: {self.rule_type}"