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
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-03-02
|
||||
@@ -0,0 +1,172 @@
|
||||
## Context
|
||||
|
||||
yaml2pptx 项目目前没有测试代码。项目采用模块化架构,包含以下模块:
|
||||
- core/: 核心领域模型(elements、presentation、template)
|
||||
- loaders/: YAML 加载层
|
||||
- validators/: 验证层(geometry、resource、result、validator)
|
||||
- renderers/: PPTX 和 HTML 渲染
|
||||
- preview/: Flask 预览服务器
|
||||
|
||||
约束条件:
|
||||
1. 必须使用 pytest 框架
|
||||
2. PPTX 文件需要实际生成和验证(Level 2:文件结构、元素数量、内容匹配、位置范围)
|
||||
3. Preview 测试不启动真实服务器
|
||||
4. 临时文件使用系统临时目录并自动清理
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
- 建立全面的测试体系,覆盖单元、集成、端到端三个层级
|
||||
- 确保核心功能的正确性和稳定性
|
||||
- 为未来重构提供安全网
|
||||
- 测试代码结构清晰、易于维护
|
||||
|
||||
**Non-Goals:**
|
||||
- 性能测试
|
||||
- UI/视觉对比测试(像素级)
|
||||
- 100% 代码覆盖率(追求合理覆盖而非完美数字)
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1: 测试目录结构
|
||||
|
||||
采用三层测试结构:
|
||||
```
|
||||
tests/
|
||||
├── unit/ # 单元测试 - 测试独立函数/类
|
||||
├── integration/ # 集成测试 - 测试模块间协作
|
||||
├── e2e/ # 端到端测试 - 测试完整用户场景
|
||||
└── fixtures/ # 测试数据
|
||||
```
|
||||
|
||||
**理由**:清晰的分层便于理解和维护,符合测试最佳实践。
|
||||
|
||||
### D2: Fixtures 策略
|
||||
|
||||
使用 pytest 的 conftest.py 集中管理共享 fixtures:
|
||||
- `temp_dir`: 临时目录(使用 pytest 内置 tmp_path)
|
||||
- `sample_yaml`: 最小可用 YAML 文件
|
||||
- `sample_image`: 测试图片(使用 Pillow 创建)
|
||||
- `sample_template`: 测试模板文件和目录
|
||||
- `pptx_validator`: PPTX 验证工具实例
|
||||
|
||||
**理由**:集中管理避免重复,便于维护。
|
||||
|
||||
### D3: PPTX 验证方案
|
||||
|
||||
创建专门的 PptxFileValidator 工具类(Level 2 验证):
|
||||
- 文件级:存在、可打开
|
||||
- 幻灯片级:数量、尺寸
|
||||
- 元素级:类型、数量、内容、位置(容差 0.1 英寸)
|
||||
|
||||
**理由**:Level 2 平衡了覆盖度和复杂度,无需图像对比库。
|
||||
|
||||
### D4: Preview 测试方案
|
||||
|
||||
不启动真实 Flask 服务器,测试以下内容:
|
||||
- `generate_preview_html()` 函数的 HTML 生成
|
||||
- `create_flask_app()` 的路由配置
|
||||
- `YAMLChangeHandler` 的文件变化检测(Mock watchdog)
|
||||
|
||||
**理由**:避免异步服务器的复杂性,测试核心逻辑。
|
||||
|
||||
### D5: Mock 边界
|
||||
|
||||
**需要 Mock:**
|
||||
- `webbrowser.open()`(避免打开浏览器)
|
||||
- `watchdog.Observer`(避免文件监听)
|
||||
- CLI 的 `sys.argv`(使用 CliRunner)
|
||||
|
||||
**不 Mock:**
|
||||
- `python-pptx`(实际生成和验证)
|
||||
- 文件系统(使用临时目录)
|
||||
- `yaml.safe_load()`(实际解析)
|
||||
|
||||
**理由**:核心生成逻辑必须真实测试,外部依赖可以 Mock。
|
||||
|
||||
### D6: 测试数据组织
|
||||
|
||||
```
|
||||
tests/fixtures/
|
||||
├── yaml_samples/
|
||||
│ ├── minimal.yaml # 最小示例
|
||||
│ ├── full_features.yaml # 包含所有功能
|
||||
│ ├── edge_cases/ # 边界情况
|
||||
│ └── invalid/ # 无效样本(测试错误处理)
|
||||
├── templates/ # 测试模板
|
||||
└── images/ # 测试图片
|
||||
```
|
||||
|
||||
**理由**:测试数据与代码分离,便于复用和维护。
|
||||
|
||||
### D7: 临时文件清理
|
||||
|
||||
方案:使用 pytest 内置 `tmp_path` fixture,自动管理临时目录。
|
||||
|
||||
**理由**:pytest 原生支持,无需手动清理代码。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk 1: PPTX 验证可能不够精确
|
||||
**描述**:Level 2 验证不检查像素级渲染效果。
|
||||
|
||||
**缓解措施**:手动验证关键用例的视觉效果,自动化测试覆盖结构正确性。
|
||||
|
||||
### Risk 2: 测试运行时间较长
|
||||
**描述**:实际生成 PPTX 文件会增加测试时间。
|
||||
|
||||
**缓解措施**:不考虑时间限制,优先保证测试覆盖度。
|
||||
|
||||
### Risk 3: 全局变量影响测试
|
||||
**描述**:preview/server.py 使用全局变量(app、change_queue 等)。
|
||||
|
||||
**缓解措施**:在测试中显式重置全局状态,或重构代码减少全局变量依赖。
|
||||
|
||||
### Risk 4: CLI 测试复杂性
|
||||
**描述**:yaml2pptx.py 是单体脚本,难以单独导入测试。
|
||||
|
||||
**缓解措施**:使用 `subprocess` 运行命令并检查输出/退出码。
|
||||
|
||||
## Migration Plan
|
||||
|
||||
### 步骤
|
||||
|
||||
1. **配置测试环境**
|
||||
- 更新 pyproject.toml 添加测试依赖
|
||||
- 创建 tests/conftest.py
|
||||
|
||||
2. **实现测试基础设施**
|
||||
- 创建 tests/conftest_pptx.py(PPTX 验证工具)
|
||||
- 创建 tests/fixtures/ 目录和测试数据
|
||||
|
||||
3. **实现单元测试**
|
||||
- test_elements.py
|
||||
- test_template.py
|
||||
- test_validators/*.py
|
||||
- test_loaders/test_yaml_loader.py
|
||||
- test_utils.py
|
||||
|
||||
4. **实现集成测试**
|
||||
- test_presentation.py
|
||||
- test_rendering_flow.py
|
||||
- test_validation_flow.py
|
||||
|
||||
5. **实现端到端测试**
|
||||
- test_convert_cmd.py
|
||||
- test_check_cmd.py
|
||||
- test_preview_cmd.py
|
||||
|
||||
6. **更新文档**
|
||||
- README.md 添加测试运行说明
|
||||
- README_DEV.md 添加测试开发指南
|
||||
|
||||
### 回滚策略
|
||||
|
||||
如果测试引入问题:
|
||||
1. 测试代码位于独立目录,不影响生产代码
|
||||
2. 可以通过删除 tests/ 目录完全移除
|
||||
3. pyproject.toml 的测试依赖是可选的
|
||||
|
||||
## Open Questions
|
||||
|
||||
无。所有技术决策已明确。
|
||||
@@ -0,0 +1,56 @@
|
||||
## Why
|
||||
|
||||
yaml2pptx 项目目前没有任何测试代码,存在以下风险:
|
||||
1. 代码重构和功能迭代时缺乏安全网,容易引入回归问题
|
||||
2. 验证器、渲染器等核心模块的逻辑复杂,缺少自动化验证
|
||||
3. 新功能开发时无法快速验证正确性
|
||||
4. 无法保证 PPTX 生成质量的一致性
|
||||
|
||||
现在项目架构已稳定,核心功能基本完成,是建立测试体系的最佳时机。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 新增完整的测试目录结构 `tests/`,包含单元测试、集成测试、端到端测试
|
||||
- 新增 `pyproject.toml` 测试依赖配置(pytest、pytest-cov 等)
|
||||
- 新增 `tests/conftest.py` 配置共享 fixtures
|
||||
- 新增 `tests/conftest_pptx.py` PPTX 文件验证辅助工具
|
||||
- 新增 `tests/fixtures/` 测试数据目录(YAML 样本、模板、图片)
|
||||
- 实现约 150+ 测试用例覆盖所有核心模块
|
||||
- 测试将实际生成 PPTX 文件并进行 Level 2 验证(文件结构、元素数量、内容匹配、位置范围)
|
||||
- Preview 测试采用方案 A(不启动真实服务器,测试 HTML 生成函数和路由配置)
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `test-framework`: pytest 测试框架基础设施,包含配置、fixtures、临时文件管理
|
||||
- `unit-tests`: 单元测试,覆盖各模块独立功能(elements、template、validators、loaders、utils)
|
||||
- `integration-tests`: 集成测试,覆盖模块间协作(presentation、渲染流程、验证流程)
|
||||
- `e2e-tests`: 端到端测试,覆盖 CLI 命令(convert、check、preview)
|
||||
- `pptx-validation`: PPTX 文件验证工具,支持文件级别、幻灯片级别、元素级别的验证
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
无。测试是新增能力,不修改现有功能的行为要求。
|
||||
|
||||
## Impact
|
||||
|
||||
### 代码影响
|
||||
- 新增 `tests/` 目录及所有测试文件
|
||||
- 修改 `pyproject.toml` 添加测试依赖
|
||||
- 可能需要调整部分代码以提升可测试性(如全局变量处理)
|
||||
|
||||
### 依赖增加
|
||||
- `pytest`: 测试框架
|
||||
- `pytest-cov`: 覆盖率报告(可选)
|
||||
- `pytest-mock`: Mock 工具(可选)
|
||||
- `pillow`: 用于创建测试图片
|
||||
|
||||
### 开发流程
|
||||
- 开发者可通过 `uv run pytest` 运行测试
|
||||
- 提交代码前应确保测试通过
|
||||
- 新功能开发应同步编写测试
|
||||
|
||||
### 文档更新
|
||||
- `README.md` 添加测试运行说明
|
||||
- `README_DEV.md` 添加测试开发指南
|
||||
@@ -0,0 +1,96 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Convert 命令端到端测试
|
||||
系统 SHALL 提供 convert 命令的端到端测试。
|
||||
|
||||
#### Scenario: 基本转换
|
||||
- **WHEN** 执行 `yaml2pptx.py convert input.yaml output.pptx`
|
||||
- **THEN** 输出文件成功生成
|
||||
- **AND** 文件可以打开并包含正确内容
|
||||
|
||||
#### Scenario: 自动输出文件名
|
||||
- **WHEN** 执行 `yaml2pptx.py convert input.yaml`(不指定输出)
|
||||
- **THEN** 使用输入文件名生成 .pptx 文件
|
||||
|
||||
#### Scenario: 使用模板
|
||||
- **WHEN** 执行转换时指定 --template-dir
|
||||
- **THEN** 模板被正确加载和应用
|
||||
|
||||
#### Scenario: 跳过验证
|
||||
- **WHEN** 执行转换时指定 --skip-validation
|
||||
- **THEN** 验证步骤被跳过
|
||||
|
||||
#### Scenario: 强制覆盖
|
||||
- **WHEN** 输出文件已存在并使用 --force
|
||||
- **THEN** 现有文件被覆盖
|
||||
|
||||
#### Scenario: 文件已存在不强制
|
||||
- **WHEN** 输出文件已存在且不使用 --force
|
||||
- **THEN** 程序提示文件已存在并退出
|
||||
|
||||
#### Scenario: 无效输入文件
|
||||
- **WHEN** 输入文件不存在
|
||||
- **THEN** 程序显示错误信息并退出
|
||||
|
||||
#### Scenario: 包含所有元素类型的转换
|
||||
- **WHEN** YAML 包含所有元素类型(文本、图片、形状、表格)
|
||||
- **THEN** 生成的 PPTX 包含所有元素并正确渲染
|
||||
|
||||
### Requirement: Check 命令端到端测试
|
||||
系统 SHALL 提供 check 命令的端到端测试。
|
||||
|
||||
#### Scenario: 验证通过
|
||||
- **WHEN** 执行 `yaml2pptx.py check valid.yaml`
|
||||
- **THEN** 显示验证通过消息
|
||||
- **AND** 退出码为 0
|
||||
|
||||
#### Scenario: 验证失败
|
||||
- **WHEN** 执行 `yaml2pptx.py check invalid.yaml`
|
||||
- **THEN** 显示错误信息
|
||||
- **AND** 退出码非 0
|
||||
|
||||
#### Scenario: 验证包含警告
|
||||
- **WHEN** YAML 文件有问题但不阻止转换
|
||||
- **THEN** 显示警告信息
|
||||
- **AND** 验证标记为通过
|
||||
|
||||
#### Scenario: 使用模板验证
|
||||
- **WHEN** YAML 使用模板并指定 --template-dir
|
||||
- **THEN** 模板文件也被验证
|
||||
|
||||
#### Scenario: 多错误报告
|
||||
- **WHEN** YAML 文件包含多个错误
|
||||
- **THEN** 所有错误被列出
|
||||
- **AND** 每个错误包含位置信息
|
||||
|
||||
### Requirement: Preview 命令端到端测试
|
||||
系统 SHALL 提供 preview 命令的端到端测试(不启动真实服务器)。
|
||||
|
||||
#### Scenario: HTML 生成
|
||||
- **WHEN** 调用 generate_preview_html() 并传入有效 YAML
|
||||
- **THEN** 返回完整的 HTML 页面
|
||||
- **AND** HTML 包含所有幻灯片的渲染
|
||||
|
||||
#### Scenario: HTML 包含幻灯片元素
|
||||
- **WHEN** 生成的预览 HTML
|
||||
- **THEN** 每张幻灯片包含正确的元素渲染
|
||||
- **AND** CSS 样式正确应用
|
||||
|
||||
#### Scenario: 错误处理
|
||||
- **WHEN** YAML 文件包含错误
|
||||
- **THEN** generate_preview_html() 返回错误页面 HTML
|
||||
- **AND** 错误信息正确显示
|
||||
|
||||
#### Scenario: SSE 事件流路由
|
||||
- **WHEN** 访问 /events 路由
|
||||
- **THEN** 返回 text/event-stream 内容类型
|
||||
|
||||
#### Scenario: 文件变化处理
|
||||
- **WHEN** YAML 文件被修改
|
||||
- **THEN** YAMLChangeHandler 检测到变化
|
||||
- **AND** 将 'reload' 消息放入队列
|
||||
|
||||
#### Scenario: Flask 应用创建
|
||||
- **WHEN** 调用 create_flask_app()
|
||||
- **THEN** 返回配置好的 Flask 应用
|
||||
- **AND** 包含 / 和 /events 路由
|
||||
@@ -0,0 +1,77 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Presentation 类集成测试
|
||||
系统 SHALL 提供 Presentation 类的集成测试,验证模板加载和幻灯片渲染。
|
||||
|
||||
#### Scenario: 幻灯片渲染
|
||||
- **WHEN** 调用 Presentation.render_slide() 并传入幻灯片数据
|
||||
- **THEN** 返回渲染后的元素列表
|
||||
- **AND** 模板变量被正确替换
|
||||
|
||||
#### Scenario: 模板缓存
|
||||
- **WHEN** 多次调用 Presentation.get_template() 并使用相同模板名
|
||||
- **THEN** 返回缓存的 Template 实例
|
||||
|
||||
#### Scenario: 模板变量传递
|
||||
- **WHEN** 幻灯片使用模板并提供 vars
|
||||
- **THEN** 变量被正确传递给模板并渲染
|
||||
|
||||
### Requirement: 渲染流程集成测试
|
||||
系统 SHALL 提供完整的 YAML 到 PPTX 渲染流程测试。
|
||||
|
||||
#### Scenario: 完整渲染流程
|
||||
- **WHEN** 从 YAML 文件加载演示文稿并生成 PPTX
|
||||
- **THEN** PPTX 文件成功生成
|
||||
- **AND** 文件包含正确数量的幻灯片
|
||||
- **AND** 每张幻灯片包含正确的元素
|
||||
|
||||
#### Scenario: 文本元素渲染
|
||||
- **WHEN** 渲染包含文本元素的幻灯片
|
||||
- **THEN** 生成的 PPTX 包含文本框
|
||||
- **AND** 文本内容、字体、颜色、对齐方式正确
|
||||
|
||||
#### Scenario: 图片元素渲染
|
||||
- **WHEN** 渲染包含图片元素的幻灯片
|
||||
- **THEN** 生成的 PPTX 包含图片
|
||||
- **AND** 图片位置和尺寸正确
|
||||
|
||||
#### Scenario: 形状元素渲染
|
||||
- **WHEN** 渲染包含形状元素的幻灯片
|
||||
- **THEN** 生成的 PPTX 包含形状
|
||||
- **AND** 形状类型、填充、边框正确
|
||||
|
||||
#### Scenario: 表格元素渲染
|
||||
- **WHEN** 渲染包含表格元素的幻灯片
|
||||
- **THEN** 生成的 PPTX 包含表格
|
||||
- **AND** 表格行列数、内容、样式正确
|
||||
|
||||
#### Scenario: 背景渲染
|
||||
- **WHEN** 渲染包含背景的幻灯片
|
||||
- **THEN** 生成的 PPTX 幻灯片背景正确设置
|
||||
|
||||
#### Scenario: 模板幻灯片渲染
|
||||
- **WHEN** 渲染使用模板的幻灯片
|
||||
- **THEN** 模板被正确加载和渲染
|
||||
- **AND** 模板变量被正确替换
|
||||
|
||||
### Requirement: 验证流程集成测试
|
||||
系统 SHALL 提供完整验证流程的集成测试。
|
||||
|
||||
#### Scenario: 完整验证流程
|
||||
- **WHEN** 调用 Validator.validate() 并传入有效 YAML 文件
|
||||
- **THEN** 返回 valid=True 的 ValidationResult
|
||||
- **AND** errors 列表为空
|
||||
|
||||
#### Scenario: 多错误收集
|
||||
- **WHEN** YAML 文件包含多个错误
|
||||
- **THEN** ValidationResult 包含所有发现的错误
|
||||
- **AND** 每个错误包含正确的位置信息
|
||||
|
||||
#### Scenario: 错误和警告分类
|
||||
- **WHEN** YAML 文件包含错误和警告
|
||||
- **THEN** ValidationResult 分别将问题分类到 errors 和 warnings
|
||||
|
||||
#### Scenario: 验证结果格式化
|
||||
- **WHEN** 调用 ValidationResult.format_output()
|
||||
- **THEN** 返回格式化的字符串
|
||||
- **AND** 包含错误、警告、提示的分级显示
|
||||
@@ -0,0 +1,76 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: PPTX 文件验证工具
|
||||
系统 SHALL 提供 PPTX 文件验证工具类,支持文件级别、幻灯片级别、元素级别的验证。
|
||||
|
||||
#### Scenario: 文件级别验证
|
||||
- **WHEN** 验证生成的 PPTX 文件
|
||||
- **THEN** 文件存在且大小大于 0
|
||||
- **AND** 文件可以被 python-pptx 打开
|
||||
|
||||
#### Scenario: 幻灯片数量验证
|
||||
- **WHEN** 验证 PPTX 文件
|
||||
- **THEN** 幻灯片数量与预期一致
|
||||
|
||||
#### Scenario: 幻灯片尺寸验证
|
||||
- **WHEN** 验证 16:9 PPTX 文件
|
||||
- **THEN** 幻灯片宽度为 10 英寸,高度为 5.625 英寸
|
||||
- **AND** 验证 4:3 PPTX 文件时,高度为 7.5 英寸
|
||||
|
||||
#### Scenario: 文本元素验证
|
||||
- **WHEN** 验证包含文本的幻灯片
|
||||
- **THEN** 找到文本框元素
|
||||
- **AND** 文本内容与预期一致
|
||||
- **AND** 字体大小、颜色、对齐方式正确
|
||||
- **AND** 位置在合理范围内(允许 0.1 英寸误差)
|
||||
|
||||
#### Scenario: 图片元素验证
|
||||
- **WHEN** 验证包含图片的幻灯片
|
||||
- **THEN** 找到图片元素
|
||||
- **AND** 图片尺寸和位置与预期一致
|
||||
- **AND** 位置在合理范围内
|
||||
|
||||
#### Scenario: 形状元素验证
|
||||
- **WHEN** 验证包含形状的幻灯片
|
||||
- **THEN** 找到形状元素
|
||||
- **AND** 形状类型正确
|
||||
- **AND** 填充颜色和边框样式正确
|
||||
- **AND** 位置在合理范围内
|
||||
|
||||
#### Scenario: 表格元素验证
|
||||
- **WHEN** 验证包含表格的幻灯片
|
||||
- **THEN** 找到表格元素
|
||||
- **AND** 行列数与预期一致
|
||||
- **AND** 单元格内容与预期一致
|
||||
- **AND** 表头样式正确应用
|
||||
|
||||
#### Scenario: 背景验证
|
||||
- **WHEN** 验证包含背景色的幻灯片
|
||||
- **THEN** 幻灯片背景颜色与预期一致
|
||||
|
||||
#### Scenario: 元素数量验证
|
||||
- **WHEN** 验证幻灯片
|
||||
- **THEN** 元素数量与预期一致
|
||||
- **AND** 元素类型分布正确
|
||||
|
||||
#### Scenario: 位置范围验证
|
||||
- **WHEN** 验证元素位置
|
||||
- **THEN** 元素位置在幻灯片范围内
|
||||
- **AND** 允许 0.1 英寸的容忍误差
|
||||
|
||||
### Requirement: 验证辅助函数
|
||||
系统 SHALL 提供验证辅助函数,简化测试代码。
|
||||
|
||||
#### Scenario: 颜色值比较
|
||||
- **WHEN** 比较 PPTX 颜色与预期颜色
|
||||
- **THEN** 验证辅助函数正确比较 RGB 值
|
||||
- **AND** 考虑颜色转换误差
|
||||
|
||||
#### Scenario: 位置比较
|
||||
- **WHEN** 比较元素位置与预期位置
|
||||
- **THEN** 验证辅助函数考虑容忍度
|
||||
|
||||
#### Scenario: 批量验证
|
||||
- **WHEN** 一次验证多个属性
|
||||
- **THEN** 验证辅助函数返回所有验证结果
|
||||
- **AND** 包含详细的失败信息
|
||||
@@ -0,0 +1,42 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Pytest 测试框架配置
|
||||
项目 SHALL 使用 pytest 作为测试框架,通过 pyproject.toml 配置测试依赖和运行参数。
|
||||
|
||||
#### Scenario: 配置测试依赖
|
||||
- **WHEN** 开发者在 pyproject.toml 中配置测试依赖
|
||||
- **THEN** 项目包含 pytest、pytest-cov、pytest-mock 等依赖
|
||||
|
||||
#### Scenario: 运行测试
|
||||
- **WHEN** 开发者执行 `uv run pytest`
|
||||
- **THEN** 所有测试被发现并执行
|
||||
|
||||
### Requirement: 共享 Fixtures
|
||||
测试框架 SHALL 提供 conftest.py 文件,定义所有测试共享的 fixtures。
|
||||
|
||||
#### Scenario: 临时目录 fixture
|
||||
- **WHEN** 测试使用 `temp_dir` fixture
|
||||
- **THEN** 系统创建一个临时目录并在测试后自动清理
|
||||
|
||||
#### Scenario: 测试 YAML 文件 fixture
|
||||
- **WHEN** 测试使用 `sample_yaml` fixture
|
||||
- **THEN** 系统创建一个包含最小可用内容的测试 YAML 文件
|
||||
|
||||
#### Scenario: 测试图片 fixture
|
||||
- **WHEN** 测试使用 `sample_image` fixture
|
||||
- **THEN** 系统创建一个测试用图片文件
|
||||
|
||||
#### Scenario: 测试模板 fixture
|
||||
- **WHEN** 测试使用 `sample_template` fixture
|
||||
- **THEN** 系统创建包含测试模板的目录
|
||||
|
||||
### Requirement: 临时文件管理
|
||||
测试生成的临时 PPTX 文件 SHALL 存放在系统临时目录,测试后自动清理。
|
||||
|
||||
#### Scenario: 临时 PPTX 输出目录
|
||||
- **WHEN** 测试生成 PPTX 文件
|
||||
- **THEN** 文件存放在系统临时目录的 yaml2pptx_tests 子目录下
|
||||
|
||||
#### Scenario: 自动清理
|
||||
- **WHEN** 测试运行完成
|
||||
- **THEN** 所有生成的 test_*.pptx 文件被删除
|
||||
@@ -0,0 +1,123 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 元素类单元测试
|
||||
系统 SHALL 为所有元素类(TextElement、ImageElement、ShapeElement、TableElement)提供单元测试。
|
||||
|
||||
#### Scenario: TextElement 创建验证
|
||||
- **WHEN** 创建 TextElement 实例
|
||||
- **THEN** box 参数被验证为包含 4 个数字的列表
|
||||
- **AND** 无效的 box 会引发 ValueError
|
||||
|
||||
#### Scenario: TextElement 颜色验证
|
||||
- **WHEN** TextElement 的 font.color 格式无效
|
||||
- **THEN** validate() 返回包含 INVALID_COLOR_FORMAT 错误的 ValidationIssue 列表
|
||||
|
||||
#### Scenario: TextElement 字体大小验证
|
||||
- **WHEN** TextElement 的 font.size 小于 8pt
|
||||
- **THEN** validate() 返回包含 FONT_TOO_SMALL 警告的 ValidationIssue 列表
|
||||
|
||||
#### Scenario: ImageElement 创建验证
|
||||
- **WHEN** 创建 ImageElement 实例
|
||||
- **THEN** src 参数必须非空
|
||||
- **AND** 空的 src 会引发 ValueError
|
||||
|
||||
#### Scenario: ShapeElement 类型验证
|
||||
- **WHEN** ShapeElement 的 shape 类型不支持
|
||||
- **THEN** validate() 返回包含 INVALID_SHAPE_TYPE 错误的 ValidationIssue 列表
|
||||
|
||||
#### Scenario: TableElement 数据验证
|
||||
- **WHEN** TableElement 的 data 行列数不一致
|
||||
- **THEN** validate() 返回包含 TABLE_INCONSISTENT_COLUMNS 错误的 ValidationIssue 列表
|
||||
|
||||
#### Scenario: 元素工厂函数
|
||||
- **WHEN** 调用 create_element() 并传入不同 type
|
||||
- **THEN** 返回对应类型的元素对象
|
||||
- **AND** 不支持的 type 会引发 ValueError
|
||||
|
||||
### Requirement: 模板系统单元测试
|
||||
系统 SHALL 为模板系统(Template 类)提供单元测试。
|
||||
|
||||
#### Scenario: 模板初始化验证
|
||||
- **WHEN** Template 初始化时未指定 templates_dir
|
||||
- **THEN** 引发 YAMLError
|
||||
|
||||
#### Scenario: 模板名称验证
|
||||
- **WHEN** Template 初始化时模板名称包含路径分隔符
|
||||
- **THEN** 引发 YAMLError
|
||||
|
||||
#### Scenario: 变量解析
|
||||
- **WHEN** 调用 resolve_value() 并包含变量引用
|
||||
- **THEN** 返回解析后的值
|
||||
- **AND** 未定义的变量会引发 YAMLError
|
||||
|
||||
#### Scenario: 条件渲染评估
|
||||
- **WHEN** 调用 evaluate_condition() 并传入条件表达式
|
||||
- **THEN** 返回正确的布尔值
|
||||
|
||||
#### Scenario: 模板渲染
|
||||
- **WHEN** 调用 render() 并提供变量值
|
||||
- **THEN** 返回渲染后的元素列表
|
||||
- **AND** 缺少必需变量会引发 YAMLError
|
||||
|
||||
### Requirement: 验证器单元测试
|
||||
系统 SHALL 为所有验证器提供单元测试。
|
||||
|
||||
#### Scenario: 几何验证器 - 元素边界检查
|
||||
- **WHEN** 元素超出页面边界
|
||||
- **THEN** GeometryValidator 返回 ELEMENT_OUT_OF_BOUNDS 警告
|
||||
|
||||
#### Scenario: 几何验证器 - 完全在页面外
|
||||
- **WHEN** 元素完全在页面外
|
||||
- **THEN** GeometryValidator 返回 ELEMENT_COMPLETELY_OUT_OF_BOUNDS 警告
|
||||
|
||||
#### Scenario: 资源验证器 - 图片检查
|
||||
- **WHEN** 图片文件不存在
|
||||
- **THEN** ResourceValidator 返回 IMAGE_FILE_NOT_FOUND 错误
|
||||
|
||||
#### Scenario: 资源验证器 - 模板检查
|
||||
- **WHEN** 模板文件不存在
|
||||
- **THEN** ResourceValidator 返回 TEMPLATE_FILE_NOT_FOUND 错误
|
||||
|
||||
#### Scenario: 主验证器协调
|
||||
- **WHEN** Validator.validate() 执行
|
||||
- **THEN** 调用所有子验证器
|
||||
- **AND** 按级别分类问题(ERROR/WARNING/INFO)
|
||||
|
||||
### Requirement: YAML 加载器单元测试
|
||||
系统 SHALL 为 YAML 加载器提供单元测试。
|
||||
|
||||
#### Scenario: 文件不存在
|
||||
- **WHEN** 加载不存在的文件
|
||||
- **THEN** 引发 YAMLError 并包含 "文件不存在" 消息
|
||||
|
||||
#### Scenario: YAML 语法错误
|
||||
- **WHEN** 加载包含语法错误的 YAML 文件
|
||||
- **THEN** 引发 YAMLError 并包含错误行号信息
|
||||
|
||||
#### Scenario: 演示文稿结构验证
|
||||
- **WHEN** data 缺少 slides 字段
|
||||
- **THEN** validate_presentation_yaml() 引发 YAMLError
|
||||
|
||||
#### Scenario: 模板结构验证
|
||||
- **WHEN** 模板 data 缺少 elements 字段
|
||||
- **THEN** validate_template_yaml() 引发 YAMLError
|
||||
|
||||
### Requirement: 工具函数单元测试
|
||||
系统 SHALL 为工具函数提供单元测试。
|
||||
|
||||
#### Scenario: 颜色转换 - 完整格式
|
||||
- **WHEN** 调用 hex_to_rgb() 并传入 #RRGGBB 格式
|
||||
- **THEN** 返回正确的 (R, G, B) 元组
|
||||
|
||||
#### Scenario: 颜色转换 - 短格式
|
||||
- **WHEN** 调用 hex_to_rgb() 并传入 #RGB 格式
|
||||
- **THEN** 返回正确的 (R, G, B) 元组
|
||||
|
||||
#### Scenario: 颜色转换 - 无效格式
|
||||
- **WHEN** 调用 hex_to_rgb() 并传入无效格式
|
||||
- **THEN** 引发 ValueError
|
||||
|
||||
#### Scenario: 颜色格式验证
|
||||
- **WHEN** 调用 validate_color() 并传入有效颜色
|
||||
- **THEN** 返回 True
|
||||
- **AND** 无效颜色返回 False
|
||||
@@ -0,0 +1,75 @@
|
||||
## 1. 测试环境配置
|
||||
|
||||
- [x] 1.1 更新 pyproject.toml 添加测试依赖(pytest、pytest-cov、pytest-mock、pillow)
|
||||
- [x] 1.2 创建 tests/conftest.py 配置共享 fixtures
|
||||
- [x] 1.3 创建 tests/__init__.py 空文件
|
||||
|
||||
## 2. 测试基础设施
|
||||
|
||||
- [x] 2.1 创建 tests/conftest_pptx.py 实现 PptxFileValidator 工具类
|
||||
- [x] 2.2 创建 tests/fixtures/ 目录结构
|
||||
- [x] 2.3 创建 tests/fixtures/yaml_samples/minimal.yaml 最小示例
|
||||
- [x] 2.4 创建 tests/fixtures/yaml_samples/full_features.yaml 完整功能示例
|
||||
- [x] 2.5 创建 tests/fixtures/yaml_samples/edge_cases/ 边界情况样本
|
||||
- [x] 2.6 创建 tests/fixtures/yaml_samples/invalid/ 无效样本
|
||||
- [x] 2.7 创建 tests/fixtures/templates/test_template.yaml 测试模板
|
||||
- [x] 2.8 添加创建测试图片的 fixture 函数(已在 conftest.py 中实现)
|
||||
|
||||
## 3. 单元测试 - 元素类
|
||||
|
||||
- [x] 3.1 创建 tests/unit/test_elements.py 并实现 TextElement 测试
|
||||
- [x] 3.2 实现 ImageElement 测试
|
||||
- [x] 3.3 实现 ShapeElement 测试
|
||||
- [x] 3.4 实现 TableElement 测试
|
||||
- [x] 3.5 实现 create_element() 工厂函数测试
|
||||
|
||||
## 4. 单元测试 - 模板系统
|
||||
|
||||
- [x] 4.1 创建 tests/unit/test_template.py 并实现模板初始化测试
|
||||
- [x] 4.2 实现变量解析测试(resolve_value、resolve_element)
|
||||
- [x] 4.3 实现条件渲染测试(evaluate_condition)
|
||||
- [x] 4.4 实现模板渲染测试(render)
|
||||
|
||||
## 5. 单元测试 - 验证器
|
||||
|
||||
- [x] 5.1 创建 tests/unit/test_validators/ 目录
|
||||
- [x] 5.2 创建 tests/unit/test_validators/test_geometry.py 并实现边界检查测试
|
||||
- [x] 5.3 创建 tests/unit/test_validators/test_resource.py 并实现资源验证测试
|
||||
- [x] 5.4 创建 tests/unit/test_validators/test_result.py 并实现验证结果测试
|
||||
- [x] 5.5 创建 tests/unit/test_validators/test_validator.py 并实现主验证器测试
|
||||
|
||||
## 6. 单元测试 - 其他模块
|
||||
|
||||
- [x] 6.1 创建 tests/unit/test_loaders/test_yaml_loader.py 并实现加载测试
|
||||
- [x] 6.2 创建 tests/unit/test_utils.py 并实现工具函数测试
|
||||
- [x] 6.3 创建 tests/unit/test_validators/__init__.py 空文件
|
||||
- [x] 6.4 创建 tests/unit/test_loaders/__init__.py 空文件
|
||||
|
||||
## 7. 集成测试
|
||||
|
||||
- [x] 7.1 创建 tests/integration/test_presentation.py 并实现 Presentation 类测试
|
||||
- [x] 7.2 创建 tests/integration/test_rendering_flow.py 并实现渲染流程测试
|
||||
- [x] 7.3 实现文本元素渲染集成测试
|
||||
- [x] 7.4 实现图片元素渲染集成测试
|
||||
- [x] 7.5 实现形状元素渲染集成测试
|
||||
- [x] 7.6 实现表格元素渲染集成测试
|
||||
- [x] 7.7 实现背景渲染集成测试
|
||||
- [x] 7.8 创建 tests/integration/test_validation_flow.py 并实现验证流程测试
|
||||
|
||||
## 8. 端到端测试
|
||||
|
||||
- [x] 8.1 创建 tests/e2e/test_convert_cmd.py 并实现基本转换测试
|
||||
- [x] 8.2 实现自动输出文件名测试
|
||||
- [x] 8.3 实现使用模板测试
|
||||
- [x] 8.4 实现跳过验证测试
|
||||
- [x] 8.5 实现强制覆盖测试
|
||||
- [x] 8.6 实现无效输入文件测试
|
||||
- [x] 8.7 创建 tests/e2e/test_check_cmd.py 并实现验证通过测试
|
||||
- [x] 8.8 实现验证失败测试
|
||||
- [x] 8.9 创建 tests/e2e/test_preview_cmd.py 并实现 HTML 生成测试
|
||||
|
||||
## 9. 文档更新
|
||||
|
||||
- [x] 9.1 更新 README.md 添加测试运行说明
|
||||
- [x] 9.2 更新 README_DEV.md 添加测试开发指南
|
||||
- [x] 9.3 在 README.md 中添加测试覆盖率要求说明
|
||||
Reference in New Issue
Block a user