5.6 KiB
5.6 KiB
测试框架使用指南
概述
项目已配置 pytest 测试框架,相比你之前的手动测试方法,有以下优势:
✅ 改进点
| 旧方法 (Jupyter Notebook) | 新方法 (pytest) |
|---|---|
| 手动运行每个测试用例 | 自动发现和运行所有测试 |
| 手动读取和对比文件 | 自动化断言和差异报告 |
| 难以定位失败原因 | 清晰的错误堆栈和 diff |
| 无法批量运行 | 支持参数化和并行测试 |
| 无覆盖率统计 | 自动生成覆盖率报告 |
快速开始
1. 运行所有测试
python -m pytest
2. 运行特定测试文件
python -m pytest tests/test_playlist_merge.py -v
3. 在 VS Code 中运行
- 按
Ctrl+Shift+P - 输入 "Run Task"
- 选择 "运行所有测试" 或其他测试任务
测试文件说明
已创建的测试文件
tests/
├── __init__.py # 包初始化
├── conftest.py # pytest fixtures 和配置
├── test_playlist_merge.py # 播放列表合并测试
└── README.md # 详细测试指南
测试用例覆盖
test_playlist_merge.py 包含:
-
基础功能测试 (
TestPlaylistMergeBasics)test_load_paths_removes_comments- 测试路径加载test_save_paths_adds_header- 测试文件保存test_empty_playlist_merge- 测试空播放列表合并
-
本地优先测试 (
TestPlaylistMergeLocalPriority)- 参数化测试 case1-4 的本地优先合并
-
远程优先测试 (
TestPlaylistMergeRemotePriority)- 参数化测试 case1-4 的远程优先合并
-
冲突检测测试 (
TestConflictDetection)- 测试冲突识别和解决
常用命令
基础运行
# 运行所有测试
pytest
# 详细输出
pytest -v
# 显示 print 输出
pytest -s
# 只运行特定测试
pytest tests/test_playlist_merge.py::TestPlaylistMergeBasics::test_load_paths_removes_comments
测试筛选
# 运行特定 case
pytest -k "case_num-1"
# 运行包含特定关键字的测试
pytest -k "local_priority"
# 运行标记的测试
pytest -m unit
调试和重试
# 失败时进入调试器
pytest --pdb
# 只运行上次失败的测试
pytest --lf
# 先运行失败的测试
pytest --ff
# 遇到第一个失败就停止
pytest -x
覆盖率报告
# 生成覆盖率报告
pytest --cov=app --cov-report=html
# 在浏览器中查看
# 打开 htmlcov/index.html
# 终端中显示覆盖率
pytest --cov=app --cov-report=term
编写新测试
1. 创建测试文件
在 tests/ 目录下创建 test_<feature>.py
2. 编写测试类和函数
import pytest
class TestMyFeature:
"""测试我的功能"""
def test_basic_case(self):
"""测试基本用例"""
result = my_function()
assert result == expected_value
@pytest.mark.parametrize("input,expected", [
(1, 2),
(2, 4),
(3, 6),
])
def test_multiple_cases(self, input, expected):
"""参数化测试多个用例"""
assert my_function(input) == expected
3. 使用 fixtures
@pytest.fixture
def sample_data():
"""提供测试数据"""
return {"key": "value"}
def test_with_fixture(sample_data):
assert sample_data["key"] == "value"
与旧测试方法的对比
旧方法 (test.ipynb)
# 手动循环和对比
for i in range(len(test_playlists[1])):
with open(test_playlists[1][i], 'r', encoding='utf-8') as f1, \
open(target_playlists[i], 'r', encoding='utf-8') as f2:
content1 = f1.read()
content2 = f2.read()
# 手动处理和对比...
if content1 == content2:
print(f"Test case {i+1} passed.")
else:
print(f"Test case {i+1} failed.")
新方法 (pytest)
@pytest.mark.parametrize("case_num", [1, 2, 3, 4])
def test_merge_local_priority(case_num, tmp_path):
"""自动运行所有用例,失败时显示详细 diff"""
# 加载输入
base_text = load_file(f"case{case_num}.m3u")
# ... 执行测试
result = merge_playlists(base_text, local_text, remote_text)
# 自动断言和差异报告
assert_playlists_equal(actual_file, expected_file)
持续集成
可以将测试集成到 CI/CD 流程:
# .github/workflows/test.yml (示例)
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run tests
run: pytest --cov=app
最佳实践
- 测试命名 - 使用清晰描述性的名称
- 独立性 - 每个测试应该独立运行
- 快速 - 单元测试应该快速执行
- 明确 - 一个测试只测一个功能点
- 维护 - 定期更新测试用例
故障排除
pytest 找不到
python -m pip install pytest pytest-cov
导入错误
确保项目根目录在 Python 路径中:
import sys
sys.path.insert(0, str(Path(__file__).parent.parent))
测试发现失败
检查 pytest.ini 配置和文件命名是否符合规范。
下一步
- 为其他模块添加测试 (如
plex_client.py,local_playlist.py) - 添加集成测试
- 配置 CI/CD 自动运行测试
- 设置测试覆盖率目标 (如 >80%)
参考资料
- pytest 官方文档
- pytest-cov 文档
- 项目内测试:
tests/README.md