fix: 修复测试问题,提升测试通过率
修复内容: - E2E测试命令执行方式:将 python -m uv run 改为 uv run - HTML渲染器:添加 & 字符的HTML转义 - Presentation尺寸验证:添加尺寸值类型验证 - PPTX验证器:修复文本框检测兼容性 - 验证结果格式化:修复提示信息显示 - Mock配置:修复表格渲染等测试的Mock配置 测试结果: - 修复前: 264 通过, 42 失败, 1 错误 - 修复后: 297 通过, 9 失败, 1 错误 剩余9个失败为待实现的功能增强(验证器模板变量验证)
This commit is contained in:
@@ -16,6 +16,7 @@ from pptx.enum.shapes import MSO_SHAPE
|
||||
|
||||
class PptxValidationError:
|
||||
"""验证错误信息"""
|
||||
|
||||
def __init__(self, level: str, message: str):
|
||||
self.level = level # 'ERROR' or 'WARNING'
|
||||
self.message = message
|
||||
@@ -69,13 +70,16 @@ class PptxFileValidator:
|
||||
actual = len(prs.slides)
|
||||
if actual != expected_count:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"幻灯片数量不匹配: 期望 {expected_count}, 实际 {actual}")
|
||||
PptxValidationError(
|
||||
"ERROR", f"幻灯片数量不匹配: 期望 {expected_count}, 实际 {actual}"
|
||||
)
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
def validate_slide_size(self, prs: Presentation, expected_size: str = "16:9") -> bool:
|
||||
def validate_slide_size(
|
||||
self, prs: Presentation, expected_size: str = "16:9"
|
||||
) -> bool:
|
||||
"""验证幻灯片尺寸"""
|
||||
expected = self.SIZE_16_9 if expected_size == "16:9" else self.SIZE_4_3
|
||||
actual_width = prs.slide_width.inches
|
||||
@@ -83,15 +87,19 @@ class PptxFileValidator:
|
||||
|
||||
if abs(actual_width - expected[0]) > self.TOLERANCE:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"幻灯片宽度不匹配: 期望 {expected[0]}, 实际 {actual_width}")
|
||||
PptxValidationError(
|
||||
"ERROR",
|
||||
f"幻灯片宽度不匹配: 期望 {expected[0]}, 实际 {actual_width}",
|
||||
)
|
||||
)
|
||||
return False
|
||||
|
||||
if abs(actual_height - expected[1]) > self.TOLERANCE:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"幻灯片高度不匹配: 期望 {expected[1]}, 实际 {actual_height}")
|
||||
PptxValidationError(
|
||||
"ERROR",
|
||||
f"幻灯片高度不匹配: 期望 {expected[1]}, 实际 {actual_height}",
|
||||
)
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -113,8 +121,11 @@ class PptxFileValidator:
|
||||
counts["text_box"] += 1
|
||||
elif hasattr(shape, "image"):
|
||||
counts["picture"] += 1
|
||||
elif shape.shape_type in [MSO_SHAPE.RECTANGLE, MSO_SHAPE.OVAL,
|
||||
MSO_SHAPE.ROUNDED_RECTANGLE]:
|
||||
elif shape.shape_type in [
|
||||
MSO_SHAPE.RECTANGLE,
|
||||
MSO_SHAPE.OVAL,
|
||||
MSO_SHAPE.ROUNDED_RECTANGLE,
|
||||
]:
|
||||
counts["shape"] += 1
|
||||
elif shape.has_table:
|
||||
counts["table"] += 1
|
||||
@@ -125,10 +136,14 @@ class PptxFileValidator:
|
||||
|
||||
return counts
|
||||
|
||||
def validate_text_element(self, slide, index: int = 0,
|
||||
expected_content: Optional[str] = None,
|
||||
expected_font_size: Optional[int] = None,
|
||||
expected_color: Optional[tuple] = None) -> bool:
|
||||
def validate_text_element(
|
||||
self,
|
||||
slide,
|
||||
index: int = 0,
|
||||
expected_content: Optional[str] = None,
|
||||
expected_font_size: Optional[int] = None,
|
||||
expected_color: Optional[tuple] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
验证文本元素
|
||||
|
||||
@@ -142,7 +157,8 @@ class PptxFileValidator:
|
||||
Returns:
|
||||
验证是否通过
|
||||
"""
|
||||
text_boxes = [s for s in slide.shapes if s.shape_type == MSO_SHAPE.TEXT_BOX]
|
||||
# 通过检查是否有text_frame属性来判断是否是文本框
|
||||
text_boxes = [s for s in slide.shapes if hasattr(s, "text_frame")]
|
||||
|
||||
if index >= len(text_boxes):
|
||||
self.errors.append(
|
||||
@@ -158,8 +174,10 @@ class PptxFileValidator:
|
||||
actual_content = text_frame.text
|
||||
if actual_content != expected_content:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"文本内容不匹配: 期望 '{expected_content}', 实际 '{actual_content}'")
|
||||
PptxValidationError(
|
||||
"ERROR",
|
||||
f"文本内容不匹配: 期望 '{expected_content}', 实际 '{actual_content}'",
|
||||
)
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -168,8 +186,10 @@ class PptxFileValidator:
|
||||
actual_size = text_frame.paragraphs[0].font.size.pt
|
||||
if abs(actual_size - expected_font_size) > 1:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"字体大小不匹配: 期望 {expected_font_size}pt, 实际 {actual_size}pt")
|
||||
PptxValidationError(
|
||||
"ERROR",
|
||||
f"字体大小不匹配: 期望 {expected_font_size}pt, 实际 {actual_size}pt",
|
||||
)
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -180,20 +200,25 @@ class PptxFileValidator:
|
||||
actual_color = (actual_rgb[0], actual_rgb[1], actual_rgb[2])
|
||||
if actual_color != expected_color:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"字体颜色不匹配: 期望 RGB{expected_color}, 实际 RGB{actual_color}")
|
||||
PptxValidationError(
|
||||
"ERROR",
|
||||
f"字体颜色不匹配: 期望 RGB{expected_color}, 实际 RGB{actual_color}",
|
||||
)
|
||||
)
|
||||
return False
|
||||
except Exception:
|
||||
self.errors.append(
|
||||
PptxValidationError("WARNING", "无法获取字体颜色")
|
||||
)
|
||||
self.errors.append(PptxValidationError("WARNING", "无法获取字体颜色"))
|
||||
|
||||
return True
|
||||
|
||||
def validate_position(self, shape, expected_left: float, expected_top: float,
|
||||
expected_width: Optional[float] = None,
|
||||
expected_height: Optional[float] = None) -> bool:
|
||||
def validate_position(
|
||||
self,
|
||||
shape,
|
||||
expected_left: float,
|
||||
expected_top: float,
|
||||
expected_width: Optional[float] = None,
|
||||
expected_height: Optional[float] = None,
|
||||
) -> bool:
|
||||
"""
|
||||
验证元素位置和尺寸
|
||||
|
||||
@@ -212,15 +237,17 @@ class PptxFileValidator:
|
||||
|
||||
if abs(actual_left - expected_left) > self.TOLERANCE:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"左边距不匹配: 期望 {expected_left}, 实际 {actual_left}")
|
||||
PptxValidationError(
|
||||
"ERROR", f"左边距不匹配: 期望 {expected_left}, 实际 {actual_left}"
|
||||
)
|
||||
)
|
||||
return False
|
||||
|
||||
if abs(actual_top - expected_top) > self.TOLERANCE:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"上边距不匹配: 期望 {expected_top}, 实际 {actual_top}")
|
||||
PptxValidationError(
|
||||
"ERROR", f"上边距不匹配: 期望 {expected_top}, 实际 {actual_top}"
|
||||
)
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -228,8 +255,10 @@ class PptxFileValidator:
|
||||
actual_width = shape.width.inches
|
||||
if abs(actual_width - expected_width) > self.TOLERANCE:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"宽度不匹配: 期望 {expected_width}, 实际 {actual_width}")
|
||||
PptxValidationError(
|
||||
"ERROR",
|
||||
f"宽度不匹配: 期望 {expected_width}, 实际 {actual_width}",
|
||||
)
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -237,8 +266,10 @@ class PptxFileValidator:
|
||||
actual_height = shape.height.inches
|
||||
if abs(actual_height - expected_height) > self.TOLERANCE:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"高度不匹配: 期望 {expected_height}, 实际 {actual_height}")
|
||||
PptxValidationError(
|
||||
"ERROR",
|
||||
f"高度不匹配: 期望 {expected_height}, 实际 {actual_height}",
|
||||
)
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -265,23 +296,21 @@ class PptxFileValidator:
|
||||
)
|
||||
if actual_rgb != expected_rgb:
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR",
|
||||
f"背景颜色不匹配: 期望 RGB{expected_rgb}, 实际 RGB{actual_rgb}")
|
||||
PptxValidationError(
|
||||
"ERROR",
|
||||
f"背景颜色不匹配: 期望 RGB{expected_rgb}, 实际 RGB{actual_rgb}",
|
||||
)
|
||||
)
|
||||
return False
|
||||
except Exception as e:
|
||||
self.errors.append(
|
||||
PptxValidationError("WARNING", f"无法获取背景颜色: {e}")
|
||||
)
|
||||
self.errors.append(PptxValidationError("WARNING", f"无法获取背景颜色: {e}"))
|
||||
|
||||
return True
|
||||
|
||||
def _validate_file_exists(self, pptx_path: Path) -> bool:
|
||||
"""验证文件存在且大小大于 0"""
|
||||
if not pptx_path.exists():
|
||||
self.errors.append(
|
||||
PptxValidationError("ERROR", f"文件不存在: {pptx_path}")
|
||||
)
|
||||
self.errors.append(PptxValidationError("ERROR", f"文件不存在: {pptx_path}"))
|
||||
return False
|
||||
|
||||
if pptx_path.stat().st_size == 0:
|
||||
|
||||
Reference in New Issue
Block a user