1
0
Files
PPTX/tests/integration/test_presentation.py
lanyuanxiaoyao ab2510a400 test: add comprehensive pytest test suite
Add complete test infrastructure for yaml2pptx project with 245+ tests
covering unit, integration, and end-to-end scenarios.

Test structure:
- Unit tests: elements, template system, validators, loaders, utils
- Integration tests: presentation and rendering flows
- E2E tests: CLI commands (convert, check, preview)

Key features:
- PptxFileValidator for Level 2 PPTX validation (file structure,
  element count, content matching, position tolerance)
- Comprehensive fixtures for test data consistency
- Mock-based testing for external dependencies
- Test images generated with PIL/Pillow
- Boundary case coverage for edge scenarios

Dependencies added:
- pytest, pytest-cov, pytest-mock
- pillow (for test image generation)

Documentation updated:
- README.md: test running instructions
- README_DEV.md: test development guide

Co-authored-by: OpenSpec change: add-comprehensive-tests
2026-03-02 23:11:34 +08:00

187 lines
5.2 KiB
Python
Raw 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.
"""
Presentation 类集成测试
测试 Presentation 类的模板加载和幻灯片渲染功能
"""
import pytest
from pathlib import Path
from core.presentation import Presentation
class TestPresentationInit:
"""Presentation 初始化测试"""
def test_init_with_yaml(self, sample_yaml):
"""测试使用 YAML 文件初始化"""
pres = Presentation(str(sample_yaml))
assert pres.data is not None
assert "slides" in pres.data
def test_init_with_template_dir(self, sample_yaml, sample_template):
"""测试带模板目录初始化"""
pres = Presentation(str(sample_yaml), str(sample_template))
assert pres.template_dir == sample_template
class TestTemplateCaching:
"""模板缓存测试"""
def test_template_is_cached(self, temp_dir, sample_template):
"""测试模板被缓存"""
# 创建使用模板的 YAML
yaml_content = f"""
metadata:
size: 16:9
slides:
- template: title-slide
vars:
title: "Test"
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path), str(sample_template))
# 第一次获取模板
template1 = pres.get_template("title-slide")
# 第二次获取模板
template2 = pres.get_template("title-slide")
# 应该是同一个实例(缓存)
assert template1 is template2
class TestRenderSlide:
"""render_slide 方法测试"""
def test_render_simple_slide(self, sample_yaml):
"""测试渲染简单幻灯片"""
pres = Presentation(str(sample_yaml))
slide_data = pres.data["slides"][0]
rendered = pres.render_slide(slide_data)
assert "elements" in rendered
assert len(rendered["elements"]) > 0
def test_render_slide_with_template(self, temp_dir, sample_template):
"""测试渲染使用模板的幻灯片"""
yaml_content = f"""
metadata:
size: 16:9
slides:
- template: title-slide
vars:
title: "Test Title"
subtitle: "Test Subtitle"
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path), str(sample_template))
slide_data = pres.data["slides"][0]
rendered = pres.render_slide(slide_data)
# 模板变量应该被替换
elements = rendered["elements"]
title_elem = next(e for e in elements if e.get("type") == "text" and "Test Title" in e.get("content", ""))
assert title_elem is not None
def test_render_slide_with_conditional_element(self, temp_dir, sample_template):
"""测试条件渲染元素"""
# 有 subtitle 的情况
yaml_with = f"""
metadata:
size: 16:9
slides:
- template: title-slide
vars:
title: "Test"
subtitle: "With Subtitle"
"""
yaml_path_with = temp_dir / "test_with.yaml"
yaml_path_with.write_text(yaml_with)
pres_with = Presentation(str(yaml_path_with), str(sample_template))
slide_data = pres_with.data["slides"][0]
rendered_with = pres_with.render_slide(slide_data)
# 应该有 2 个元素title 和 subtitle 都显示)
assert len(rendered_with["elements"]) == 2
# 没有 subtitle 的情况
yaml_without = f"""
metadata:
size: 16:9
slides:
- template: title-slide
vars:
title: "Test"
"""
yaml_path_without = temp_dir / "test_without.yaml"
yaml_path_without.write_text(yaml_without)
pres_without = Presentation(str(yaml_path_without), str(sample_template))
slide_data = pres_without.data["slides"][0]
rendered_without = pres_without.render_slide(slide_data)
# 应该只有 1 个元素subtitle 不显示)
assert len(rendered_without["elements"]) == 1
def test_render_slide_with_variables(self, temp_dir, sample_template):
"""测试变量传递"""
yaml_content = f"""
metadata:
size: 16:9
slides:
- template: title-slide
vars:
title: "My Title"
subtitle: "My Subtitle"
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path), str(sample_template))
slide_data = pres.data["slides"][0]
rendered = pres.render_slide(slide_data)
# 检查变量是否被正确替换
elements = rendered["elements"]
assert any("My Title" in e.get("content", "") for e in elements)
assert any("My Subtitle" in e.get("content", "") for e in elements)
class TestPresentationWithoutTemplate:
"""无模板的演示文稿测试"""
def test_render_direct_elements(self, temp_dir):
"""测试直接渲染元素(不使用模板)"""
yaml_content = """
metadata:
size: 16:9
slides:
- elements:
- type: text
box: [1, 1, 8, 1]
content: "Direct Text"
font:
size: 24
"""
yaml_path = temp_dir / "test.yaml"
yaml_path.write_text(yaml_content)
pres = Presentation(str(yaml_path))
slide_data = pres.data["slides"][0]
rendered = pres.render_slide(slide_data)
# 元素应该直接被渲染
assert len(rendered["elements"]) == 1
assert rendered["elements"][0]["content"] == "Direct Text"