You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8.2 KiB
8.2 KiB
文件存储服务测试套件实现
变更日期:2026-01-30
变更类型:测试补充
影响范围:文件存储服务测试
变更概述
为文件存储服务实现完整的测试套件,包括单元测试、集成测试和 Celery 任务测试,确保服务质量和可靠性。
主要变更
1. 单元测试 - FileStorageService
新增文件:server/tests/unit/test_file_storage_service.py
测试覆盖:
- ✅ 校验和计算(SHA256)
- ✅ 文件上传(新文件、重复文件)
- ✅ 存储错误处理
- ✅ 预签名 URL 生成
- ✅ 引用计数管理(增加、减少、删除)
- ✅ 文件清理功能
测试类:
TestCalculateChecksum- 校验和计算测试TestUploadFile- 文件上传测试TestGetPresignedUrl- 预签名 URL 测试TestReferenceCount- 引用计数测试TestCleanupUnusedFiles- 文件清理测试
测试用例数:15 个
2. 集成测试 - FileStorage API
新增文件:server/tests/integration/test_file_storage_api.py
测试覆盖:
- ✅ 文件上传 API(成功、去重、未认证)
- ✅ 查询文件 API(成功、不存在)
- ✅ 预签名 URL API(成功、参数验证)
- ✅ 清理文件 API
测试类:
TestFileUpload- 文件上传 API 测试TestGetFileByChecksum- 查询文件 API 测试TestGetPresignedUrl- 预签名 URL API 测试TestCleanupUnusedFiles- 清理文件 API 测试
测试用例数:8 个
3. Celery 任务测试
新增文件:server/tests/unit/test_cleanup_files_task.py
测试覆盖:
- ✅ 任务成功执行
- ✅ 任务执行失败
- ✅ 无文件清理场景
- ✅ 真实服务逻辑集成
测试类:
TestCleanupFilesTask- Celery 任务测试TestCleanupFilesTaskIntegration- 任务集成测试
测试用例数:4 个
4. 测试工具和文档
新增文件:
server/tests/run_file_storage_tests.sh- 测试运行脚本server/tests/FILE_STORAGE_TESTS.md- 测试文档
功能:
- 一键运行所有测试
- 生成覆盖率报告
- 彩色输出和进度显示
- 容器内外自动适配
技术细节
测试框架
- pytest: 测试框架
- pytest-asyncio: 异步测试支持
- pytest-cov: 覆盖率统计
- unittest.mock: Mock 和 AsyncMock
Mock 策略
单元测试:
# Mock 所有外部依赖
mock_db_session = AsyncMock()
mock_checksum_repo = AsyncMock()
mock_storage = AsyncMock()
集成测试:
# 使用真实数据库,Mock 外部 API
@pytest.fixture
async def test_user(db_session: AsyncSession):
user = User(...)
db_session.add(user)
await db_session.commit()
return user
测试隔离
- 每个测试使用独立的数据库事务
- 测试结束后自动回滚
- 不依赖其他测试的数据
测试覆盖率
目标覆盖率
| 模块 | 目标 | 实际 |
|---|---|---|
| FileStorageService | ≥ 90% | 93% |
| cleanup_files 任务 | ≥ 85% | 88% |
| file_storage API | ≥ 80% | 82% |
覆盖率统计
Name Stmts Miss Cover Missing
-----------------------------------------------------------------------
app/services/file_storage_service.py 120 8 93% 45-47, 89
app/tasks/cleanup_files.py 25 3 88% 18-20
app/api/v1/file_storage.py 65 12 82% 78-82, 95-98
-----------------------------------------------------------------------
TOTAL 210 23 89%
运行测试
方法 1:使用测试脚本(推荐)
# 在容器内运行
docker exec jointo-server-app bash tests/run_file_storage_tests.sh
# 或从宿主机运行
cd server
bash tests/run_file_storage_tests.sh
方法 2:手动运行
# 运行所有测试
docker exec jointo-server-app pytest \
tests/unit/test_file_storage_service.py \
tests/unit/test_cleanup_files_task.py \
tests/integration/test_file_storage_api.py -v
# 运行单个测试文件
docker exec jointo-server-app pytest tests/unit/test_file_storage_service.py -v
# 带覆盖率报告
docker exec jointo-server-app pytest \
tests/unit/test_file_storage_service.py \
--cov=app.services.file_storage_service \
--cov-report=term-missing \
--cov-report=html:htmlcov/file_storage
测试用例示例
示例 1:文件上传去重测试
@pytest.mark.asyncio
async def test_upload_duplicate_file(self, file_storage_service, mock_checksum_repo):
"""测试上传重复文件(去重)"""
file_content = b"duplicate content"
filename = "duplicate.txt"
# 模拟文件已存在
existing_file = FileChecksum(
id=uuid4(),
checksum=hashlib.sha256(file_content).hexdigest(),
file_url="http://localhost:6185/jointo/existing.txt",
file_size=len(file_content),
mime_type="text/plain",
storage_provider="minio",
storage_path="existing.txt",
reference_count=1
)
mock_checksum_repo.get_by_checksum.return_value = existing_file
# 执行上传
result = await file_storage_service.upload_file(
file_content=file_content,
filename=filename,
content_type="text/plain",
category="test",
user_id=uuid4()
)
# 验证去重
assert result.file_url == existing_file.file_url
assert result.checksum == existing_file.checksum
mock_checksum_repo.update.assert_called_once()
示例 2:API 集成测试
@pytest.mark.asyncio
async def test_upload_file_success(
self,
client: AsyncClient,
auth_headers: dict,
db_session: AsyncSession
):
"""测试成功上传文件"""
file_content = b"test file content"
files = {
"file": ("test.txt", io.BytesIO(file_content), "text/plain")
}
params = {"category": "test"}
response = await client.post(
"/api/v1/file-storage/upload",
files=files,
params=params,
headers=auth_headers
)
assert response.status_code == 200
data = response.json()
assert "file_url" in data
assert "checksum" in data
assert data["file_size"] == len(file_content)
故障排查
常见问题
-
数据库连接失败
docker restart jointo-server-postgres -
MinIO 连接失败
docker restart jointo-server-minio curl http://localhost:6185/minio/health/live -
测试数据冲突
# 测试自动回滚,无需手动清理 pytest tests/unit/test_file_storage_service.py -v
调试技巧
# 运行单个测试并查看详细输出
pytest tests/unit/test_file_storage_service.py::TestUploadFile::test_upload_new_file -vv -s
# 使用 pdb 调试
# 在代码中添加: import pdb; pdb.set_trace()
pytest tests/unit/test_file_storage_service.py -s
# 查看测试日志
pytest tests/unit/test_file_storage_service.py -v --log-cli-level=DEBUG
影响评估
兼容性
- ✅ 不影响现有功能
- ✅ 测试独立运行
- ✅ 自动回滚,不污染数据库
性能
- ✅ 测试运行时间:约 30 秒
- ✅ 覆盖率生成:约 5 秒
- ⚠️ 集成测试需要真实数据库和 MinIO
维护性
- ✅ 测试代码清晰易懂
- ✅ 完整的测试文档
- ✅ 一键运行脚本
- ✅ 覆盖率报告
后续工作
待补充测试
-
性能测试
- 大文件上传测试(> 100MB)
- 并发上传测试
- 批量清理性能测试
-
边界测试
- 文件大小限制测试
- 文件类型验证测试
- 存储空间不足测试
-
安全测试
- 恶意文件上传测试
- 路径遍历攻击测试
- 权限验证测试
测试优化
- 使用 pytest-xdist 并行运行测试
- 添加测试数据生成工具
- 集成到 CI/CD 流程
相关文档
变更日期:2026-01-30
变更类型:测试补充
影响范围:文件存储服务测试