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.
 

6.9 KiB

项目 API 标准化测试验证计划

测试日期: 2026-02-11
测试范围: projects.py, project_resources.py, project_elements.py, project_element_tags.py

测试目标

验证 4 个项目相关 API 文件已成功完成标准化改造:

  1. 查询参数支持 camelCase
  2. 响应格式使用 SuccessResponse
  3. 异常处理统一使用 exceptions.py

测试清单

1. 异常处理测试

1.1 项目角色 API (project_elements.py)

测试场景 1: 创建重复角色名称

POST /api/v1/projects/{project_id}/characters
{
  "name": "重复角色名",
  "role_type": "protagonist"
}

预期结果:
- HTTP 状态码: 400
- 响应体: {"success": false, "code": 400, "message": "该项目下已存在同名角色,请使用其他名称", ...}

测试场景 2: 访问不存在的角色

GET /api/v1/projects/{project_id}/characters/{non_existent_id}

预期结果:
- HTTP 状态码: 404
- 响应体: {"success": false, "code": 404, "message": "角色不存在", ...}

1.2 项目场景 API (project_elements.py)

测试场景 3: 创建重复场景名称

POST /api/v1/projects/{project_id}/locations
{
  "name": "重复场景名",
  "location": "interior"
}

预期结果:
- HTTP 状态码: 400
- 响应体: {"success": false, "code": 400, "message": "该项目下已存在同名场景,请使用其他名称", ...}

1.3 项目道具 API (project_elements.py)

测试场景 4: 创建重复道具名称

POST /api/v1/projects/{project_id}/props
{
  "name": "重复道具名"
}

预期结果:
- HTTP 状态码: 400
- 响应体: {"success": false, "code": 400, "message": "该项目下已存在同名道具,请使用其他名称", ...}

1.4 项目元素标签 API (project_element_tags.py)

测试场景 5: 创建标签参数错误

POST /api/v1/projects/{project_id}/element-tags
{
  "element_type": "invalid_type",
  "element_id": "invalid_id"
}

预期结果:
- HTTP 状态码: 400
- 响应体: {"success": false, "code": 400, "message": "...", ...}

测试场景 6: 更新不存在的标签

PUT /api/v1/projects/{project_id}/element-tags/{non_existent_id}
{
  "tag_label": "新标签名"
}

预期结果:
- HTTP 状态码: 404
- 响应体: {"success": false, "code": 404, "message": "...", ...}

测试场景 7: 删除不存在的标签

DELETE /api/v1/projects/{project_id}/element-tags/{non_existent_id}

预期结果:
- HTTP 状态码: 404
- 响应体: {"success": false, "code": 404, "message": "...", ...}

测试场景 8: 设置不存在的默认标签

PUT /api/v1/projects/{project_id}/elements/character/{element_id}/default-tag
{
  "tag_id": "{non_existent_tag_id}"
}

预期结果:
- HTTP 状态码: 404
- 响应体: {"success": false, "code": 404, "message": "...", ...}

2. camelCase 查询参数测试

2.1 项目列表 API (projects.py)

测试场景 9: 使用 camelCase 查询参数

GET /api/v1/projects?folderId={folder_id}&contentType=movie&sortBy=createdAt&sortOrder=desc&pageSize=10

预期结果:
- HTTP 状态码: 200
- 响应体包含项目列表
- 分页信息正确

2.2 项目素材 API (project_resources.py)

测试场景 10: 使用 camelCase 查询参数

GET /api/v1/projects/{project_id}/resources?elementTagId={tag_id}&pageSize=20

预期结果:
- HTTP 状态码: 200
- 响应体包含素材列表
- 按标签过滤正确

2.3 项目标签 API (project_element_tags.py)

测试场景 11: 使用 camelCase 查询参数

GET /api/v1/projects/{project_id}/element-tags?elementType=character

预期结果:
- HTTP 状态码: 200
- 响应体只包含角色类型的标签

3. 响应格式验证

3.1 成功响应格式

所有成功请求应返回统一格式:

{
  "success": true,
  "code": 200,
  "message": "Success",
  "data": { ... },
  "timestamp": "2026-02-11T10:00:00+00:00"
}

3.2 错误响应格式

所有错误请求应返回统一格式:

{
  "success": false,
  "code": 400,  //  404, 403, 500 
  "message": "具体错误消息",
  "data": null,
  "timestamp": "2026-02-11T10:00:00+00:00"
}

自动化测试建议

Pytest 测试用例示例

import pytest
from httpx import AsyncClient

@pytest.mark.asyncio
async def test_create_duplicate_character_returns_validation_error(
    async_client: AsyncClient,
    auth_headers: dict,
    project_id: str
):
    """测试创建重复角色返回 ValidationError (400)"""
    # 第一次创建
    response1 = await async_client.post(
        f"/api/v1/projects/{project_id}/characters",
        headers=auth_headers,
        json={"name": "主角", "role_type": "protagonist"}
    )
    assert response1.status_code == 200
    
    # 第二次创建(重复名称)
    response2 = await async_client.post(
        f"/api/v1/projects/{project_id}/characters",
        headers=auth_headers,
        json={"name": "主角", "role_type": "protagonist"}
    )
    
    # 验证返回 ValidationError
    assert response2.status_code == 400
    data = response2.json()
    assert data["success"] is False
    assert data["code"] == 400
    assert "已存在同名角色" in data["message"]


@pytest.mark.asyncio
async def test_get_project_tags_with_camelcase_params(
    async_client: AsyncClient,
    auth_headers: dict,
    project_id: str
):
    """测试查询参数支持 camelCase"""
    response = await async_client.get(
        f"/api/v1/projects/{project_id}/element-tags",
        headers=auth_headers,
        params={"elementType": "character"}  # camelCase 参数
    )
    
    assert response.status_code == 200
    data = response.json()
    assert data["success"] is True
    assert data["code"] == 200
    
    # 验证返回的都是角色标签
    for tag in data["data"]:
        assert tag["element_type"] == "character"

回归测试

兼容性验证

  1. 验证 HTTP 状态码未改变
  2. 验证响应格式保持一致
  3. 验证现有前端功能正常运行

性能测试

  1. 验证异常处理未引入性能问题
  2. 验证查询参数解析性能正常

测试通过标准

  • 所有唯一约束冲突返回 400 ValidationError
  • 所有资源不存在返回 404 NotFoundError
  • 所有权限不足返回 403 PermissionError
  • 所有服务器错误返回 500 InternalServerError
  • 查询参数 camelCase 别名正常工作
  • 响应格式符合 SuccessResponse 规范
  • 错误消息清晰易懂
  • 现有功能未受影响

注意事项

  1. 不要在生产环境直接测试 - 使用开发或测试环境
  2. 保存测试数据 - 某些测试会创建/删除数据
  3. 测试顺序 - 先测试创建,再测试更新/删除
  4. 清理测试数据 - 测试完成后清理创建的测试数据

测试工具推荐

  1. Postman - 手动 API 测试
  2. Pytest + httpx - 自动化测试
  3. curl - 命令行快速测试
  4. Swagger UI - 交互式 API 文档测试 (/docs)