""" API测试用例模块(增强版) 支持参数化测试、边界条件测试和异常场景测试 """ from typing import List, Dict, Any, Callable from functools import wraps import pytest from core.api_tester import APITester from core.validation import ValidationRule from data.test_data import TestDataGenerator def ensure_auth(test_func: Callable) -> Callable: """ 装饰器:确保测试前已认证 Args: test_func: 测试函数 Returns: 包装后的测试函数 """ @wraps(test_func) def wrapper(self, *args, **kwargs): # 确保已认证 if not self.tester._ensure_authenticated(): return False return test_func(self, *args, **kwargs) return wrapper class APITestCases: """API测试用例集合(增强版)""" def __init__(self, tester: APITester): """ 初始化测试用例 Args: tester: API测试器实例 """ self.tester = tester self.test_data_generator = TestDataGenerator() self.created_user_id = None self.created_role_id = None @ensure_auth def test_health_check(self) -> bool: """ 测试健康检查接口 Returns: 是否通过 """ result = self.tester.request( "GET", "/actuator/health", test_name="健康检查", expected_status=200, require_auth=False ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", "UP", path="status") ] result = self.tester.validate(result, validation_rules) return result.passed def test_login(self, username: str = None, password: str = None) -> bool: """ 测试用户登录 Args: username: 用户名 password: 密码 Returns: 是否通过 """ username = username or "admin" password = password or "admin123" result = self.tester.request( "POST", "/auth/login", data={"username": username, "password": password}, test_name="用户登录", expected_status=200, require_auth=False ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code"), ValidationRule("json_path", "token", path="data.token") ] result = self.tester.validate(result, validation_rules) return result.passed @ensure_auth def test_get_user_list(self) -> bool: """ 测试获取用户列表 Returns: 是否通过 """ result = self.tester.request( "GET", "/user/list", params={"page": 1, "pageSize": 10}, test_name="获取用户列表", expected_status=200 ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code"), ValidationRule("json_path", "records", path="data") ] result = self.tester.validate(result, validation_rules) return result.passed @ensure_auth def test_get_role_list(self) -> bool: """ 测试获取角色列表 Returns: 是否通过 """ result = self.tester.request( "GET", "/role/list", params={"page": 1, "pageSize": 10}, test_name="获取角色列表", expected_status=200 ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code"), ValidationRule("json_path", "records", path="data") ] result = self.tester.validate(result, validation_rules) return result.passed @ensure_auth def test_get_menu_list(self) -> bool: """ 测试获取菜单列表 Returns: 是否通过 """ result = self.tester.request( "GET", "/menu/list", test_name="获取菜单列表", expected_status=200 ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code"), ValidationRule("json_path", "list", path="data") ] result = self.tester.validate(result, validation_rules) return result.passed @ensure_auth def test_create_user(self) -> bool: """ 测试创建用户 Returns: 是否通过 """ user_data = self.test_data_generator.generate_user_data() result = self.tester.request( "POST", "/user/create", data=user_data, test_name="创建用户", expected_status=200 ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code"), ValidationRule("json_path", user_data["username"], path="data.username") ] result = self.tester.validate(result, validation_rules) # 保存创建的用户ID if result.passed and result.response_data.get("data"): self.created_user_id = result.response_data["data"].get("id") return result.passed @ensure_auth def test_create_role(self) -> bool: """ 测试创建角色 Returns: 是否通过 """ role_data = self.test_data_generator.generate_role_data() result = self.tester.request( "POST", "/role/create", data=role_data, test_name="创建角色", expected_status=200 ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code"), ValidationRule("json_path", role_data["roleName"], path="data.roleName") ] result = self.tester.validate(result, validation_rules) # 保存创建的角色ID if result.passed and result.response_data.get("data"): self.created_role_id = result.response_data["data"].get("id") return result.passed @ensure_auth def test_update_user(self, user_id: int = None) -> bool: """ 测试更新用户 Args: user_id: 用户ID Returns: 是否通过 """ user_data = self.test_data_generator.generate_user_data() if user_id: user_data["id"] = user_id elif self.created_user_id: user_data["id"] = self.created_user_id result = self.tester.request( "PUT", "/user/update", data=user_data, test_name="更新用户", expected_status=200 ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code") ] result = self.tester.validate(result, validation_rules) return result.passed @ensure_auth def test_delete_user(self, user_id: int = None) -> bool: """ 测试删除用户 Args: user_id: 用户ID Returns: 是否通过 """ if user_id is None: user_id = self.created_user_id if user_id is None: return False result = self.tester.request( "DELETE", f"/user/delete/{user_id}", test_name="删除用户", expected_status=200 ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code") ] result = self.tester.validate(result, validation_rules) return result.passed @ensure_auth def test_get_user_info(self, user_id: int = None) -> bool: """ 测试获取用户信息 Args: user_id: 用户ID Returns: 是否通过 """ if user_id is None: user_id = self.created_user_id if user_id is None: return False result = self.tester.request( "GET", f"/user/info/{user_id}", test_name="获取用户信息", expected_status=200 ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code"), ValidationRule("json_path", user_id, path="data.id") ] result = self.tester.validate(result, validation_rules) return result.passed @ensure_auth def test_search_users(self, keyword: str = None) -> bool: """ 测试搜索用户 Args: keyword: 搜索关键词 Returns: 是否通过 """ keyword = keyword or "admin" result = self.tester.request( "GET", "/user/search", params={"keyword": keyword, "page": 1, "pageSize": 10}, test_name="搜索用户", expected_status=200 ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code"), ValidationRule("json_path", "records", path="data") ] result = self.tester.validate(result, validation_rules) return result.passed def run_all_tests(self) -> Dict[str, bool]: """ 运行所有基础测试用例 Returns: 测试结果字典 """ results = {} # 健康检查 results["health_check"] = self.test_health_check() # 登录 results["login"] = self.test_login() # 获取列表 results["get_user_list"] = self.test_get_user_list() results["get_role_list"] = self.test_get_role_list() results["get_menu_list"] = self.test_get_menu_list() # 创建 results["create_user"] = self.test_create_user() results["create_role"] = self.test_create_role() # 搜索 results["search_users"] = self.test_search_users() return results class ParameterizedTestCases: """参数化测试用例""" def __init__(self, tester: APITester): """ 初始化参数化测试用例 Args: tester: API测试器实例 """ self.tester = tester self.test_data_generator = TestDataGenerator() @ensure_auth def test_login_with_different_credentials(self, credentials: List[Dict[str, str]]) -> Dict[str, bool]: """ 使用不同凭据测试登录 Args: credentials: 凭据列表,每个元素包含username和password Returns: 测试结果字典 """ results = {} for cred in credentials: username = cred.get("username") password = cred.get("password") test_name = f"登录测试 - {username}" result = self.tester.request( "POST", "/auth/login", data={"username": username, "password": password}, test_name=test_name, expected_status=200, require_auth=False ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code") ] result = self.tester.validate(result, validation_rules) results[test_name] = result.passed return results @ensure_auth def test_pagination(self, page_sizes: List[int]) -> Dict[str, bool]: """ 测试分页功能 Args: page_sizes: 页面大小列表 Returns: 测试结果字典 """ results = {} for page_size in page_sizes: test_name = f"分页测试 - 页面大小: {page_size}" result = self.tester.request( "GET", "/user/list", params={"page": 1, "pageSize": page_size}, test_name=test_name, expected_status=200 ) validation_rules = [ ValidationRule("status_code", 200), ValidationRule("json_path", 200, path="code"), ValidationRule("json_path", "records", path="data") ] result = self.tester.validate(result, validation_rules) results[test_name] = result.passed return results class BoundaryTestCases: """边界条件测试用例""" def __init__(self, tester: APITester): """ 初始化边界条件测试用例 Args: tester: API测试器实例 """ self.tester = tester self.test_data_generator = TestDataGenerator() @ensure_auth def test_user_name_length(self) -> Dict[str, bool]: """ 测试用户名长度边界 Returns: 测试结果字典 """ results = {} # 测试空用户名 result = self.tester.request( "POST", "/auth/login", data={"username": "", "password": "admin123"}, test_name="登录测试 - 空用户名", expected_status=400, require_auth=False ) results["空用户名"] = result.status_code == 400 # 测试超长用户名 long_username = "a" * 100 result = self.tester.request( "POST", "/auth/login", data={"username": long_username, "password": "admin123"}, test_name="登录测试 - 超长用户名", expected_status=400, require_auth=False ) results["超长用户名"] = result.status_code == 400 return results @ensure_auth def test_page_size_boundaries(self) -> Dict[str, bool]: """ 测试页面大小边界 Returns: 测试结果字典 """ results = {} # 测试页面大小为0 result = self.tester.request( "GET", "/user/list", params={"page": 1, "pageSize": 0}, test_name="分页测试 - 页面大小为0", expected_status=400 ) results["页面大小为0"] = result.status_code == 400 # 测试页面大小为负数 result = self.tester.request( "GET", "/user/list", params={"page": 1, "pageSize": -1}, test_name="分页测试 - 页面大小为负数", expected_status=400 ) results["页面大小为负数"] = result.status_code == 400 # 测试超大页面大小 result = self.tester.request( "GET", "/user/list", params={"page": 1, "pageSize": 10000}, test_name="分页测试 - 超大页面大小", expected_status=200 ) results["超大页面大小"] = result.status_code == 200 return results class ExceptionTestCases: """异常场景测试用例""" def __init__(self, tester: APITester): """ 初始化异常场景测试用例 Args: tester: API测试器实例 """ self.tester = tester self.test_data_generator = TestDataGenerator() @ensure_auth def test_invalid_credentials(self) -> Dict[str, bool]: """ 测试无效凭据 Returns: 测试结果字典 """ results = {} # 测试错误密码 result = self.tester.request( "POST", "/auth/login", data={"username": "admin", "password": "wrongpassword"}, test_name="登录测试 - 错误密码", expected_status=401, require_auth=False ) results["错误密码"] = result.status_code == 401 # 测试不存在的用户 result = self.tester.request( "POST", "/auth/login", data={"username": "nonexistent", "password": "admin123"}, test_name="登录测试 - 不存在的用户", expected_status=401, require_auth=False ) results["不存在的用户"] = result.status_code == 401 return results @ensure_auth def test_missing_required_fields(self) -> Dict[str, bool]: """ 测试缺少必填字段 Returns: 测试结果字典 """ results = {} # 测试缺少用户名 result = self.tester.request( "POST", "/auth/login", data={"password": "admin123"}, test_name="登录测试 - 缺少用户名", expected_status=400, require_auth=False ) results["缺少用户名"] = result.status_code == 400 # 测试缺少密码 result = self.tester.request( "POST", "/auth/login", data={"username": "admin"}, test_name="登录测试 - 缺少密码", expected_status=400, require_auth=False ) results["缺少密码"] = result.status_code == 400 return results @ensure_auth def test_unauthorized_access(self) -> Dict[str, bool]: """ 测试未授权访问 Returns: 测试结果字典 """ results = {} # 临时清除认证 self.tester.auth_manager.logout() # 测试未授权访问用户列表 result = self.tester.request( "GET", "/user/list", test_name="未授权访问 - 用户列表", expected_status=401, require_auth=False ) results["未授权访问用户列表"] = result.status_code == 401 # 重新认证 self.tester._ensure_authenticated() return results @ensure_auth def test_invalid_http_methods(self) -> Dict[str, bool]: """ 测试无效的HTTP方法 Returns: 测试结果字典 """ results = {} # 测试不支持的HTTP方法 try: result = self.tester.request( "PATCH", "/user/list", test_name="无效HTTP方法 - PATCH", expected_status=405 ) results["PATCH方法"] = result.status_code == 405 except: results["PATCH方法"] = False return results