测试策略与实践
目录
引言
本文件为 capcut-mate 项目制定全面的测试策略与实践指南,覆盖单元测试、集成测试、手动测试与专项测试的组织方式;明确测试文件命名规范、用例编写标准与断言模式;给出 API 接口、业务逻辑、服务层与跨平台功能的测试示例;说明测试数据准备、Mock 对象使用与测试环境配置;阐述持续集成中的测试执行流程与覆盖率建议,并补充性能与压力测试方法,以保障代码质量与系统稳定性。
项目结构
capcut-mate 的测试组织位于 tests 目录,采用按功能模块划分的文件布局,结合 pytest 进行自动化测试,同时保留部分手动测试脚本用于交互式验证与探索性测试。核心测试类型包括:
- 单元测试:针对服务层函数与工具函数进行隔离测试,常配合 Mock。
- 集成测试:通过 TestClient 发起端到端请求,验证路由、中间件与服务链路。
- 手动测试:通过独立脚本进行交互式验证与边界条件探索。
- 专项测试:针对特定功能领域的深度测试,如跨平台兼容性、错误处理等。
graph TB
subgraph "测试目录 tests/"
T1["test_api_version.py"]
T2["test_draft_service.py"]
T3["test_middleware.py"]
T4["manual_test_audio_infos.py"]
T5["test_add_audios.py"]
T6["test_add_videos_refactor.py"]
T7["test_search_sticker.py"]
T8["test_media_utils.py"]
T9["test_logic_validation.py"]
T10["test_imgs_infos_multiple_animations.py"]
T11["test_cross_platform.py"]
T12["test_ci_dependencies.py"]
T13["test_export_error_handling.py"]
T14["test_file_operations.py"]
T15["test_transform_coordinate_fix.py"]
T16["test_video_transform_fix.py"]
T0["__init__.py"]
end
T0 --> T1
T0 --> T2
T0 --> T3
T0 --> T4
T0 --> T5
T0 --> T6
T0 --> T7
T0 --> T8
T0 --> T9
T0 --> T10
T0 --> T11
T0 --> T12
T0 --> T13
T0 --> T14
T0 --> T15
T0 --> T16
核心组件
- 测试框架与运行器
- 使用 pytest 作为测试运行器,支持标记、夹具、参数化与插件扩展。
- 集成测试通过 fastapi.testclient.TestClient 发起请求,无需真实外部依赖。
- 测试文件命名规范
- 单元测试:test_*.py,如 test_draft_service.py、test_media_utils.py。
- 手动测试:manualtest*.py,如 manual_test_audio_infos.py。
- 集成测试:test_*_api.py 或 test_api_version.py,如 test_api_version.py。
- 专项测试:test_fix.py 或 test_improvement.py,如 test_transform_coordinate_fix.py。
- 断言模式
- 基于 pytest 的 assert 语法,结合状态码、响应体键存在性与值校验。
- 使用 pytest-mock 提供的 mocker 参数进行对象与模块级 Mock。
- 测试数据准备
- 通过构造 JSON 字符串或 Python 字典传入服务层函数,避免外部资源依赖。
- 对媒体时长等场景,使用本地文件或占位文件进行验证。
- Mock 对象使用
- 使用 mocker.patch 替换第三方库或内部模块行为,验证调用次数与参数。
- 对 DraftFolder 等外部依赖进行模拟,确保测试稳定与可重复。
- 测试环境配置
- 通过 TestClient 启动应用实例,注册中间件与路由,保证与生产一致的上下文。
- 手动测试脚本通过 sys.path 插入项目根目录,导入 src 下模块。
架构总览
下图展示了测试架构与被测系统的交互关系,包括应用入口、路由、中间件与服务层,以及测试客户端与 Mock 的位置。新增的专项测试覆盖了跨平台兼容性、错误处理、文件操作和坐标变换等关键领域。
graph TB
subgraph "应用层"
APP["FastAPI 应用<br/>main.py"]
ROUTER["路由 v1_router<br/>src/router/v1.py"]
MW_PREP["中间件 PrepareMiddleware<br/>src/middlewares/prepare.py"]
MW_RESP["中间件 ResponseMiddleware<br/>src/middlewares/response.py"]
SVC["服务层模块<br/>src/service/*"]
UTILS["工具层模块<br/>src/utils/*"]
END
subgraph "测试层"
TC["TestClient<br/>pytest"]
MOCK["pytest-mock<br/>mocker"]
MANUAL["手动测试脚本<br/>manual_test_*.py"]
SP1["专项测试<br/>跨平台兼容性"]
SP2["专项测试<br/>错误处理"]
SP3["专项测试<br/>文件操作"]
SP4["专项测试<br/>坐标变换修复"]
end
TC --> APP
APP --> ROUTER
APP --> MW_PREP
APP --> MW_RESP
ROUTER --> SVC
SVC --> UTILS
MOCK --> SVC
MOCK --> UTILS
MANUAL --> SVC
MANUAL --> UTILS
SP1 --> SVC
SP1 --> UTILS
SP2 --> SVC
SP2 --> UTILS
SP3 --> UTILS
SP4 --> UTILS
详细组件分析
API 版本与路由测试
- 目标:验证路由注册、版本控制与错误处理。
- 关键点:
- 使用 TestClient 访问 /openapi/v1/create_draft 与不存在的 /openapi/v2/create_draft。
- 断言状态码与响应体字段,确保消息与草稿 ID 存在。
- 示例参考
- test_v1_create_draft
- test_version_not_found
sequenceDiagram
participant C as "客户端(TestClient)"
participant A as "FastAPI 应用(main.py)"
participant R as "路由(v1_router)"
participant S as "服务层(示例 : create_draft)"
C->>A : "POST /openapi/v1/create_draft"
A->>R : "分发请求"
R->>S : "调用服务函数"
S-->>R : "返回草稿信息"
R-->>A : "封装响应"
A-->>C : "200 OK + JSON"
服务层函数与 Mock 测试
- 目标:验证服务函数行为与外部依赖交互。
- 关键点:
- 使用 mocker.patch 替换 DraftFolder 等外部模块,模拟创建草稿流程。
- 断言 Mock 调用次数与保存行为,确保服务函数正确驱动底层实现。
- 示例参考
- test_create_draft_service
- test_create_draft_api
flowchart TD
Start(["进入测试"]) --> Patch["使用 mocker.patch 替换外部依赖"]
Patch --> CallSvc["调用服务函数 create_draft_service(...)"]
CallSvc --> AssertCalls["断言 Mock 调用次数与参数"]
AssertCalls --> SaveCheck["断言 save() 是否被调用"]
SaveCheck --> Done(["断言 draft_id 非空"])
中间件集成测试
- 目标:验证中间件初始化环境变量与目录存在性。
- 关键点:
- 在测试应用中注册中间件,访问根路径获取环境变量与目录状态。
- 通过 uvicorn 启动测试服务器进行手动验证。
- 示例参考
- 中间件测试路由
sequenceDiagram
participant U as "浏览器/客户端"
participant A as "测试应用"
participant MW as "中间件(init_env_middleware)"
participant FS as "文件系统"
U->>A : "GET /"
A->>MW : "进入中间件处理"
MW->>FS : "检查目录是否存在"
FS-->>MW : "返回存在性"
MW-->>A : "注入环境变量"
A-->>U : "返回包含环境变量与目录状态的响应"
手动测试:音频信息生成
- 目标:验证音频信息 JSON 生成逻辑与参数处理。
- 关键点:
- 输入 MP3 URL 列表与时间线,输出符合预期的 JSON 字符串。
- 验证可选参数 audio_effect 与 volume 的存在与缺失场景。
- 示例参考
- audio_infos
- test_audio_infos
集成测试:添加音频接口
- 目标:验证从创建草稿到添加音频的完整链路。
- 关键点:
- 通过 requests 发起 HTTP 请求,先创建草稿,再添加音频。
- 断言响应状态码与返回字段,确保返回 track_id、audio_ids 与 draft_url。
- 示例参考
- test_add_audios
单元测试:视频解析与时长处理
- 目标:验证视频数据解析与 duration 处理逻辑。
- 关键点:
- 输入包含 duration 与不包含 duration 的场景,断言最终 duration 与播放时长(end-start)。
- 验证指定 duration 与实际播放时长的关系,确保修复逻辑正确。
- 示例参考
- test_parse_video_data_with_duration
- test_duration_handling_logic
单元测试:贴纸搜索
- 目标:验证贴纸搜索功能在不同关键词下的行为。
- 关键点:
- 正常搜索、无结果搜索与空关键词的返回数量与结构验证。
- 示例参考
- test_search_sticker
单元测试:媒体工具
- 目标:验证媒体时长获取与格式化工具。
- 关键点:
- 对不存在文件与存在文件分别进行断言,验证返回值与格式化输出。
- 示例参考
- test_media_duration
新增测试功能
多动画功能测试
- 目标:验证图片多动画功能的增强处理能力,包括动画扩展、类型分配和向后兼容性。
- 关键点:
- 测试基本多动画功能:为每张图片分配不同的入场动画。
- 验证动画扩展逻辑:当动画数量少于图片数量时,使用最后一个动画填充。
- 测试多种动画类型同时使用:入场、循环和出场动画的协调处理。
- 确保向后兼容性:单个动画仍能正常工作。
- 处理空动画和None值:验证空字符串和None值的正确处理。
- 示例参考
- test_multiple_animations_basic
- test_animation_extension_logic
- test_multiple_animation_types
flowchart TD
Start(["多动画测试开始"]) --> Basic["基本多动画测试"]
Basic --> Extend["动画扩展逻辑测试"]
Extend --> Types["多种动画类型测试"]
Types --> Compatibility["向后兼容性测试"]
Compatibility --> Empty["空动画处理测试"]
Empty --> End(["测试完成"])
跨平台兼容性测试
- 目标:验证项目在不同操作系统(Windows/Linux)上的兼容性和功能可用性。
- 关键点:
- 基础导入测试:验证核心模块在不同平台上的导入成功。
- 服务层和API层导入:确保各层模块在跨平台环境下的可用性。
- 工具层导入:验证工具函数和辅助模块的跨平台兼容性。
- 平台特定功能:Windows平台的UI自动化和Linux平台的占位符功能。
- 剪映控制器可用性:根据平台特性检测功能可用性。
- 示例参考
- test_cross_platform_compatibility
graph TB
Platform["平台检测"] --> ImportTests["导入测试"]
ImportTests --> ServiceLayer["服务层导入"]
ImportTests --> APILayer["API层导入"]
ImportTests --> UtilsLayer["工具层导入"]
Platform --> Windows["Windows特定测试"]
Platform --> Linux["Linux特定测试"]
Windows --> UIAutomation["UI自动化测试"]
Linux --> Placeholder["占位符测试"]
CI/CD依赖测试
- 目标:验证构建环境中依赖安装和管理的行为,确保CI/CD流程的稳定性。
- 关键点:
- 平台信息显示:记录当前系统、版本和架构信息。
- 基础依赖同步:测试uv sync命令在不同环境下的执行。
- Windows可选依赖:验证Windows特定依赖的安装行为。
- 功能导入测试:确保核心功能在CI环境中可用。
- 跨平台依赖差异:处理不同平台间的依赖差异。
- 示例参考
- test_ci_dependencies
sequenceDiagram
participant CI as "CI环境"
participant UV as "uv包管理器"
participant Sys as "系统依赖"
CI->>UV : "uv sync 基础依赖"
UV-->>CI : "依赖同步结果"
CI->>UV : "uv pip install -e .[windows]"
UV-->>CI : "Windows可选依赖安装"
CI->>Sys : "功能导入测试"
Sys-->>CI : "导入成功/失败"
导出错误处理测试
- 目标:验证视频导出功能的错误处理机制,确保在不支持的环境下提供清晰的错误信息。
- 关键点:
- 错误处理验证:测试导出功能在缺少依赖时的异常处理。
- 平台限制检测:验证Windows平台特定功能的可用性检查。
- 错误信息验证:确保错误消息包含预期的平台相关信息。
- 异常类型检查:验证抛出正确的异常类型(RuntimeError)。
- 示例参考
- test_export_error_handling
flowchart TD
ExportStart["导出测试开始"] --> CreateTask["创建测试任务"]
CreateTask --> CallExport["调用导出功能"]
CallExport --> CatchError["捕获异常"]
CatchError --> CheckType{"检查异常类型"}
CheckType --> |RuntimeError| CheckMessage["检查错误信息"]
CheckType --> |其他异常| Unexpected["意外异常处理"]
CheckMessage --> Validate["验证错误信息内容"]
Validate --> ExportEnd["测试完成"]
Unexpected --> ExportEnd
文件操作改进测试
- 目标:验证文件移动和目录创建功能的改进,确保文件处理的可靠性和健壮性。
- 关键点:
- 文件移动测试:验证文件从源路径移动到目标路径的正确性。
- 目录创建测试:验证嵌套目录的创建和文件写入功能。
- 路径处理:确保目标目录存在且可写。
- 异常处理:验证文件操作失败时的错误处理机制。
- 示例参考
- test_file_move_improvements
- test_directory_creation
flowchart TD
FileTest["文件操作测试"] --> CreateTemp["创建临时文件"]
CreateTemp --> MoveFile["移动文件测试"]
MoveFile --> CheckExists["检查文件存在性"]
CheckExists --> CreateDir["创建嵌套目录"]
CreateDir --> WriteFile["写入测试文件"]
WriteFile --> Verify["验证操作结果"]
Verify --> FileEnd["测试完成"]
坐标变换修复测试
- 目标:验证图片transform坐标计算的修复,确保坐标转换使用正确的基准(草稿尺寸而非图片尺寸)。
- 关键点:
- 基础坐标计算:验证transform_x和transform_y使用草稿宽高进行计算。
- 不同草稿尺寸:测试多种草稿尺寸下的坐标转换准确性。
- 计算精度验证:确保坐标转换的数学计算正确性。
- 错误修复验证:确认修复解决了原有的坐标计算问题。
- 示例参考
- test_transform_coordinate_fix
- test_transform_with_different_draft_sizes
flowchart TD
CoordTest["坐标变换测试"] --> CreateDraft["创建自定义尺寸草稿"]
CreateDraft --> AddImage["添加带transform坐标的图片"]
AddImage --> CalcCoord["计算transform坐标"]
CalcCoord --> VerifyResult["验证计算结果"]
VerifyResult --> TestSizes["测试不同草稿尺寸"]
TestSizes --> VerifySizes["验证尺寸相关计算"]
VerifySizes --> CoordEnd["测试完成"]
视频变换修复测试
- 目标:验证视频transform坐标计算的修复,确保视频坐标变换与图片坐标变换的一致性。
- 关键点:
- 视频坐标计算:验证视频transform坐标使用草稿尺寸进行计算。
- 一致性测试:确保视频和图片的坐标变换计算结果一致。
- 多尺寸支持:测试不同草稿尺寸下的视频坐标变换。
- 计算逻辑验证:确认修复了坐标计算的基准问题。
- 示例参考
- test_video_transform_coordinate_fix
- test_video_transform_vs_image_transform_consistency
sequenceDiagram
participant V as "视频测试"
participant I as "图片测试"
participant D as "草稿尺寸"
V->>D : "创建草稿"
V->>V : "添加带transform的视频"
I->>D : "创建相同草稿"
I->>I : "添加带transform的图片"
V->>V : "计算视频坐标"
I->>I : "计算图片坐标"
V-->>V : "验证计算结果"
I-->>I : "验证计算结果"
V->>V : "比较两者结果"
I->>I : "比较两者结果"
依赖分析
- 测试运行时依赖
- pytest:测试运行与断言。
- pytest-mock:Mock 支持。
- fastapi.testclient:集成测试客户端。
- requests:手动集成测试发起 HTTP 请求。
- subprocess:执行系统命令和进程管理。
- platform:平台信息检测。
- tempfile:临时文件和目录管理。
- shutil:文件操作支持。
- 项目运行时依赖
- FastAPI、Uvicorn、PyMediaInfo、pywin32、uiautomation、cos-python-sdk-v5 等。
- 依赖关系可视化
graph TB
PY["pytest"]
PM["pytest-mock"]
TC["fastapi.testclient"]
REQ["requests"]
SUB["subprocess"]
PLAT["platform"]
TEMP["tempfile"]
SHUTIL["shutil"]
F["FastAPI"]
UV["Uvicorn"]
PMI["PyMediaInfo"]
WIN["pywin32/uiautomation"]
COS["cos-python-sdk-v5"]
PY --> PM
PY --> TC
PY --> REQ
PY --> SUB
PY --> PLAT
PY --> TEMP
PY --> SHUTIL
TC --> F
F --> UV
F --> PMI
F --> WIN
F --> COS
SUB --> WIN
TEMP --> SHUTIL
性能考虑
- 单元测试
- 使用 Mock 减少外部 I/O,优先断言调用次数与参数,避免真实下载或渲染。
- 新增的专项测试应尽量使用本地资源,避免网络依赖。
- 集成测试
- 通过 TestClient 本地启动应用,避免网络抖动影响测试稳定性。
- 将媒体文件大小控制在合理范围,减少测试耗时。
- 跨平台测试应避免不必要的系统调用。
- 手动测试
- 使用小样本数据集进行交互式验证,完成后清理临时文件。
- 专项测试应包含适当的超时机制。
- 性能与压力测试建议
- 使用 Locust 或自定义脚本对高频接口(如创建草稿、生成视频)进行并发压测。
- 设置合理的超时与重试策略,监控 CPU、内存与磁盘 I/O。
- 将压力测试纳入 CI,设置阈值告警(如 P95 延迟、错误率)。
- 新增的坐标变换测试应验证计算性能,避免复杂的循环操作。
故障排查指南
- 常见问题
- 服务器未启动:确保本地监听端口 30000 已启动,或调整测试脚本中的目标地址。
- 路由未注册:确认 main.py 中路由前缀与标签配置正确。
- 中间件异常:检查中间件初始化逻辑与环境变量注入。
- Mock 未生效:确认 patch 路径与模块导入路径一致。
- 跨平台兼容性问题:检查平台特定依赖和功能可用性。
- CI/CD依赖问题:验证uv命令的可用性和依赖安装状态。
- 坐标计算错误:确认使用正确的基准尺寸(草稿尺寸而非素材尺寸)。
- 排查步骤
- 使用手动测试脚本快速定位问题模块。
- 在单元测试中逐步缩小范围,替换复杂依赖为简单 Mock。
- 查看日志输出,定位异常发生的具体阶段。
- 对跨平台问题,检查平台检测和条件导入逻辑。
- 对依赖问题,验证系统命令的执行权限和环境配置。
结论
本测试策略以 pytest 为核心,结合单元测试、集成测试、手动测试与专项测试,覆盖 API、服务层、工具函数与跨平台功能的关键路径。通过 Mock 与 TestClient,确保测试稳定与可重复;通过手动测试补充探索性验证;通过专项测试增强项目的质量保证能力。新增的7个测试文件显著提升了项目的测试覆盖面,包括多动画功能、跨平台兼容性、CI/CD依赖管理、错误处理、文件操作改进、坐标变换修复等关键领域。建议在 CI 中引入覆盖率统计与性能压测,持续提升代码质量与系统稳定性。
附录
- 测试文件命名规范
- 单元测试:test_*.py
- 集成测试:test_*_api.py 或 test_api_version.py
- 手动测试:manualtest*.py
- 专项测试:test_fix.py、testimprovement.py、test*_compatibility.py
- 用例编写标准
- 每个测试函数聚焦单一行为,使用清晰的断言描述期望结果。
- 对外部依赖使用 Mock,避免真实网络或文件系统操作。
- 新增的专项测试应包含平台检测和条件执行逻辑。
- 断言模式
- 使用 pytest 的 assert 语法,结合状态码、键存在性与值比较。
- 对跨平台测试,使用platform模块进行条件断言。
- 对错误处理测试,验证异常类型和错误信息内容。
- 测试数据准备
- 构造最小可验证的数据结构,必要时使用本地占位文件。
- 专项测试应包含多样化的测试场景和边界条件。
- Mock 对象使用
- 使用 mocker.patch 替换模块或类,断言调用次数与参数。
- 跨平台测试中,使用条件Mock处理平台差异。
- 测试环境配置
- 使用 TestClient 启动应用实例,注册中间件与路由。
- 手动测试脚本通过 sys.path 插入项目根目录导入模块。
- 专项测试应包含适当的环境变量和系统命令支持。
- 持续集成与覆盖率
- 在 CI 中执行 pytest 并收集覆盖率报告,建议设置阈值(如语句覆盖率不低于 80%)。
- 将性能与压力测试纳入流水线,设置告警阈值。
- 新增专项测试应在CI中进行平台特定的条件执行。