refactor: 重构文档结构,采用渐进式信息披露模式
将 README.md 拆分为多个专题文档,减少认知负荷: - 用户文档迁移到 docs/ (用户指南、元素、模板、参考等) - 开发文档迁移到 docs/development/ (架构、模块、规范) - README.md 精简至 ~290 行,仅保留概览和导航 - 删除 README_DEV.md,内容已迁移 - 归档 OpenSpec 变更 refactor-docs-progressive-disclosure
This commit is contained in:
267
docs/development/testing.md
Normal file
267
docs/development/testing.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# 测试规范
|
||||
|
||||
本文档说明 yaml2pptx 项目的测试框架和规范。
|
||||
|
||||
## 测试框架
|
||||
|
||||
项目使用 pytest 作为测试框架,测试代码位于 `tests/` 目录。
|
||||
|
||||
## 测试结构
|
||||
|
||||
```
|
||||
tests/
|
||||
├── conftest.py # pytest 配置和共享 fixtures
|
||||
├── conftest_pptx.py # PPTX 文件验证工具
|
||||
├── unit/ # 单元测试
|
||||
│ ├── test_elements.py # 元素类测试
|
||||
│ ├── test_template.py # 模板系统测试
|
||||
│ ├── test_utils.py # 工具函数测试
|
||||
│ ├── test_validators/ # 验证器测试
|
||||
│ │ ├── test_geometry.py
|
||||
│ │ ├── test_resource.py
|
||||
│ │ ├── test_result.py
|
||||
│ │ └── test_validator.py
|
||||
│ └── test_loaders/ # 加载器测试
|
||||
│ └── test_yaml_loader.py
|
||||
├── integration/ # 集成测试
|
||||
│ ├── test_presentation.py
|
||||
│ ├── test_rendering_flow.py
|
||||
│ └── test_validation_flow.py
|
||||
├── e2e/ # 端到端测试
|
||||
│ ├── test_convert_cmd.py
|
||||
│ ├── test_check_cmd.py
|
||||
│ └── test_preview_cmd.py
|
||||
└── fixtures/ # 测试数据
|
||||
├── yaml_samples/ # YAML 样本
|
||||
├── templates/ # 测试模板
|
||||
└── images/ # 测试图片
|
||||
```
|
||||
|
||||
## 运行测试
|
||||
|
||||
### 基本命令
|
||||
|
||||
```bash
|
||||
# 安装测试依赖
|
||||
uv pip install -e ".[dev]"
|
||||
|
||||
# 运行所有测试
|
||||
uv run pytest
|
||||
|
||||
# 运行特定类型的测试
|
||||
uv run pytest tests/unit/ # 单元测试
|
||||
uv run pytest tests/integration/ # 集成测试
|
||||
uv run pytest tests/e2e/ # 端到端测试
|
||||
|
||||
# 运行特定测试文件
|
||||
uv run pytest tests/unit/test_elements.py
|
||||
|
||||
# 显示详细输出
|
||||
uv run pytest -v
|
||||
|
||||
# 显示测试覆盖率
|
||||
uv run pytest --cov=. --cov-report=html
|
||||
```
|
||||
|
||||
### 测试文件位置
|
||||
|
||||
- **自动化测试**:`tests/` 目录
|
||||
- **手动测试文件**:`temp/` 目录
|
||||
|
||||
## 编写测试
|
||||
|
||||
### 测试类命名
|
||||
|
||||
使用 `Test<ClassName>` 格式:
|
||||
|
||||
```python
|
||||
class TestTextElement:
|
||||
"""TextElement 测试类"""
|
||||
pass
|
||||
```
|
||||
|
||||
### 测试方法命名
|
||||
|
||||
使用 `test_<what_is_being_tested>` 格式:
|
||||
|
||||
```python
|
||||
def test_create_with_defaults(self):
|
||||
"""测试使用默认值创建 TextElement"""
|
||||
pass
|
||||
|
||||
def test_invalid_color_raises_error(self):
|
||||
"""测试无效颜色会引发错误"""
|
||||
pass
|
||||
```
|
||||
|
||||
### 测试示例
|
||||
|
||||
```python
|
||||
import pytest
|
||||
from core.elements import TextElement, FontConfig
|
||||
|
||||
class TestTextElement:
|
||||
"""TextElement 测试类"""
|
||||
|
||||
def test_create_with_defaults(self):
|
||||
"""测试使用默认值创建 TextElement"""
|
||||
elem = TextElement()
|
||||
assert elem.type == 'text'
|
||||
assert elem.content == ''
|
||||
assert elem.box == [1, 1, 8, 1]
|
||||
|
||||
def test_create_with_custom_values(self):
|
||||
"""测试使用自定义值创建 TextElement"""
|
||||
elem = TextElement(
|
||||
content="Test",
|
||||
box=[2, 2, 6, 1],
|
||||
font={"size": 24}
|
||||
)
|
||||
assert elem.content == "Test"
|
||||
assert elem.box == [2, 2, 6, 1]
|
||||
|
||||
def test_invalid_color_raises_error(self):
|
||||
"""测试无效颜色会引发错误"""
|
||||
with pytest.raises(ValueError, match="无效颜色"):
|
||||
TextElement(font={"color": "red"})
|
||||
```
|
||||
|
||||
## Fixtures
|
||||
|
||||
共享 fixtures 定义在 `tests/conftest.py` 中:
|
||||
|
||||
```python
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
|
||||
@pytest.fixture
|
||||
def temp_dir(tmp_path):
|
||||
"""临时目录 fixture"""
|
||||
return tmp_path
|
||||
|
||||
@pytest.fixture
|
||||
def sample_yaml(temp_dir):
|
||||
"""最小测试 YAML 文件"""
|
||||
yaml_file = temp_dir / "test.yaml"
|
||||
yaml_file.write_text("""
|
||||
metadata:
|
||||
size: "16:9"
|
||||
|
||||
slides:
|
||||
- elements:
|
||||
- type: text
|
||||
box: [1, 1, 8, 1]
|
||||
content: "Test"
|
||||
""")
|
||||
return yaml_file
|
||||
|
||||
@pytest.fixture
|
||||
def sample_image(temp_dir):
|
||||
"""测试图片 fixture"""
|
||||
import PIL.Image
|
||||
img_path = temp_dir / "test.png"
|
||||
img = PIL.Image.new('RGB', (100, 100), color='red')
|
||||
img.save(img_path)
|
||||
return img_path
|
||||
|
||||
@pytest.fixture
|
||||
def pptx_validator():
|
||||
"""PPTX 验证器 fixture"""
|
||||
from tests.conftest_pptx import PptxFileValidator
|
||||
return PptxFileValidator()
|
||||
```
|
||||
|
||||
### 使用 Fixtures
|
||||
|
||||
```python
|
||||
def test_with_fixture(sample_yaml):
|
||||
"""使用 fixture 的测试"""
|
||||
assert sample_yaml.exists()
|
||||
assert sample_yaml.stat().st_size > 0
|
||||
```
|
||||
|
||||
## PPTX 验证
|
||||
|
||||
使用 `PptxFileValidator` 验证生成的 PPTX 文件:
|
||||
|
||||
```python
|
||||
def test_pptx_generation(temp_dir, pptx_validator):
|
||||
"""测试 PPTX 生成"""
|
||||
from core.presentation import Presentation
|
||||
from renderers.pptx_renderer import PptxGenerator
|
||||
|
||||
# 生成 PPTX
|
||||
yaml_path = temp_dir / "test.yaml"
|
||||
output_path = temp_dir / "output.pptx"
|
||||
|
||||
# ... 创建演示文稿 ...
|
||||
|
||||
# 验证文件
|
||||
assert pptx_validator.validate_file(output_path) is True
|
||||
|
||||
# 验证内容
|
||||
from pptx import Presentation as PPTX
|
||||
prs = PPTX(str(output_path))
|
||||
assert len(prs.slides) == 1
|
||||
assert pptx_validator.validate_text_element(
|
||||
prs.slides[0],
|
||||
index=0,
|
||||
expected_content="Test"
|
||||
) is True
|
||||
```
|
||||
|
||||
## 手动测试
|
||||
|
||||
```bash
|
||||
# 验证 YAML 文件
|
||||
uv run yaml2pptx.py check temp/test.yaml
|
||||
|
||||
# 使用模板时验证
|
||||
uv run yaml2pptx.py check temp/demo.yaml --template ./templates.yaml
|
||||
|
||||
# 转换 YAML 为 PPTX
|
||||
uv run yaml2pptx.py convert temp/test.yaml temp/output.pptx
|
||||
|
||||
# 自动生成输出文件名
|
||||
uv run yaml2pptx.py convert temp/test.yaml
|
||||
|
||||
# 跳过自动验证
|
||||
uv run yaml2pptx.py convert temp/test.yaml temp/output.pptx --skip-validation
|
||||
|
||||
# 强制覆盖已存在文件
|
||||
uv run yaml2pptx.py convert temp/test.yaml temp/output.pptx --force
|
||||
|
||||
# 使用模板
|
||||
uv run yaml2pptx.py convert temp/demo.yaml temp/output.pptx --template ./templates.yaml
|
||||
|
||||
# 启动预览服务器
|
||||
uv run yaml2pptx.py preview temp/test.yaml
|
||||
|
||||
# 指定端口
|
||||
uv run yaml2pptx.py preview temp/test.yaml --port 8080
|
||||
|
||||
# 允许局域网访问
|
||||
uv run yaml2pptx.py preview temp/test.yaml --host 0.0.0.0
|
||||
|
||||
# 不自动打开浏览器
|
||||
uv run yaml2pptx.py preview temp/test.yaml --no-browser
|
||||
```
|
||||
|
||||
## 测试覆盖率
|
||||
|
||||
目标测试覆盖率:>80%
|
||||
|
||||
```bash
|
||||
# 生成覆盖率报告
|
||||
uv run pytest --cov=. --cov-report=html
|
||||
|
||||
# 查看报告
|
||||
open htmlcov/index.html
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [开发规范](development-guide.md) - 编码规范
|
||||
- [扩展指南](extending.md) - 添加新功能
|
||||
|
||||
[返回开发文档索引](../README.md)
|
||||
Reference in New Issue
Block a user