feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
"""
|
||||
异常处理器模块
|
||||
|
||||
提供测试异常分类处理功能,区分致命错误和可重试错误。
|
||||
"""
|
||||
|
||||
from typing import Optional, List
|
||||
from playwright.sync_api import Page
|
||||
|
||||
|
||||
class FatalTestError(Exception):
|
||||
"""致命测试错误"""
|
||||
pass
|
||||
|
||||
|
||||
class RetryableError(Exception):
|
||||
"""可重试错误"""
|
||||
pass
|
||||
|
||||
|
||||
class TestExceptionHandler:
|
||||
"""测试异常处理器"""
|
||||
|
||||
# 致命错误:立即停止测试
|
||||
FATAL_ERRORS: List[str] = [
|
||||
"Browser crashed",
|
||||
"Connection refused",
|
||||
"Target page closed",
|
||||
"Database connection failed",
|
||||
"Session deleted",
|
||||
"invalid session id",
|
||||
]
|
||||
|
||||
# 可重试错误:自动重试
|
||||
RETRYABLE_ERRORS: List[str] = [
|
||||
"TimeoutError",
|
||||
"Timeout exceeded",
|
||||
"Element not found",
|
||||
"Network error",
|
||||
"net::ERR",
|
||||
"Stale element reference",
|
||||
"element is detached",
|
||||
"Execution context was destroyed",
|
||||
"Unable to locate element",
|
||||
"waiting for locator",
|
||||
]
|
||||
|
||||
# 非致命错误:记录但继续
|
||||
NON_FATAL_ERRORS: List[str] = [
|
||||
"Screenshot failed",
|
||||
"Log write failed",
|
||||
"Screenshot is not supported",
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def handle_exception(
|
||||
cls,
|
||||
error: Exception,
|
||||
page: Optional[Page] = None,
|
||||
test_name: str = "",
|
||||
screenshot_helper=None,
|
||||
) -> Optional[Exception]:
|
||||
"""
|
||||
处理测试异常
|
||||
|
||||
Args:
|
||||
error: 异常对象
|
||||
page: Playwright页面对象
|
||||
test_name: 测试名称
|
||||
screenshot_helper: 截图辅助工具
|
||||
|
||||
Returns:
|
||||
None: 非致命错误,继续执行
|
||||
RetryableError: 可重试错误
|
||||
FatalTestError: 致命错误,停止测试
|
||||
"""
|
||||
error_msg = str(error)
|
||||
error_type = type(error).__name__
|
||||
|
||||
# 致命错误
|
||||
if any(fatal in error_msg for fatal in cls.FATAL_ERRORS):
|
||||
if screenshot_helper and page:
|
||||
screenshot_helper.take_screenshot(
|
||||
page, f"{test_name}_fatal_error" if test_name else "fatal_error"
|
||||
)
|
||||
raise FatalTestError(f"测试遇到致命错误 [{error_type}]: {error_msg}")
|
||||
|
||||
# 可重试错误
|
||||
if any(retryable in error_msg for retryable in cls.RETRYABLE_ERRORS):
|
||||
if screenshot_helper and page:
|
||||
screenshot_helper.take_screenshot(
|
||||
page,
|
||||
f"{test_name}_retryable_error" if test_name else "retryable_error",
|
||||
)
|
||||
return RetryableError(f"可重试错误 [{error_type}]: {error_msg}")
|
||||
|
||||
# 非致命错误
|
||||
if any(non_fatal in error_msg for non_fatal in cls.NON_FATAL_ERRORS):
|
||||
# 仅记录错误,不抛出
|
||||
return None
|
||||
|
||||
# 未知错误 - 根据错误类型判断
|
||||
if "assert" in error_msg.lower():
|
||||
# 断言错误通常是测试逻辑问题,不重试
|
||||
raise error
|
||||
|
||||
# 其他错误视为可重试
|
||||
if screenshot_helper and page:
|
||||
screenshot_helper.take_screenshot(
|
||||
page, f"{test_name}_unknown_error" if test_name else "unknown_error"
|
||||
)
|
||||
return RetryableError(f"未知错误 [{error_type}]: {error_msg}")
|
||||
|
||||
@classmethod
|
||||
def is_fatal_error(cls, error: Exception) -> bool:
|
||||
"""判断是否为致命错误"""
|
||||
error_msg = str(error)
|
||||
return any(fatal in error_msg for fatal in cls.FATAL_ERRORS)
|
||||
|
||||
@classmethod
|
||||
def is_retryable_error(cls, error: Exception) -> bool:
|
||||
"""判断是否为可重试错误"""
|
||||
error_msg = str(error)
|
||||
return any(retryable in error_msg for retryable in cls.RETRYABLE_ERRORS)
|
||||
Reference in New Issue
Block a user