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.8 KiB

AI 服务集成测试实施

日期: 2026-02-03
类型: 测试实施
影响范围: AI 服务测试框架

概述

实现了 AI 服务的完整集成测试框架,包括 JWT 认证、测试 fixtures 和 12 个测试用例。

实施内容

1. JWT 认证 Fixture

文件: server/tests/conftest.py

添加了 auth_headers fixture,生成真实的 JWT token 并创建 session 记录:

@pytest_asyncio.fixture
async def auth_headers(test_user: User, db_session: AsyncSession) -> dict:
    """创建认证 headers(生成真实的 JWT token 并创建 session)"""
    from app.core.security import create_access_token
    from app.models.user import UserSession
    from app.utils.id_generator import generate_uuid
    from datetime import timedelta
    
    # 生成真实的 JWT token
    access_token = create_access_token(
        data={"sub": str(test_user.user_id)}
    )
    
    # 在数据库中创建 session 记录
    session = UserSession(
        session_id=generate_uuid(),
        user_id=test_user.user_id,
        token=access_token,
        expires_at=datetime.now(timezone.utc) + timedelta(minutes=30),
        ip_address="127.0.0.1",
        user_agent="pytest"
    )
    db_session.add(session)
    await db_session.commit()
    
    return {
        "Authorization": f"Bearer {access_token}",
        "Content-Type": "application/json"
    }

关键点:

  • 使用 create_access_token 生成真实 JWT token
  • user_sessions 表中创建 session 记录(系统通过此表验证 token)
  • 设置 30 分钟过期时间

2. 测试 Fixtures

文件: server/tests/integration/test_ai_integration.py

添加了以下 fixtures:

test_project

@pytest_asyncio.fixture
async def test_project(db_session: AsyncSession, test_user: User) -> Project:
    """创建测试项目"""
    project = Project(
        project_id=generate_uuid(),
        user_id=test_user.user_id,
        owner_id=test_user.user_id,  # 必须设置 owner_id
        name="测试项目",
        description="用于测试的项目"
    )
    db_session.add(project)
    await db_session.commit()
    await db_session.refresh(project)
    
    yield project
    
    # 清理
    try:
        await db_session.refresh(project)
        await db_session.delete(project)
        await db_session.commit()
    except Exception:
        try:
            await db_session.rollback()
        except Exception:
            pass

test_screenplay

@pytest_asyncio.fixture
async def test_screenplay(
    db_session: AsyncSession,
    test_user: User,
    test_project: Project
) -> Screenplay:
    """创建测试剧本"""
    screenplay = Screenplay(
        screenplay_id=generate_uuid(),
        project_id=test_project.project_id,
        title="测试剧本",
        content="""
        场景1:咖啡馆 - 白天
        
        小明走进咖啡馆,看到小红坐在窗边。
        
        小明:你好,好久不见!
        小红:是啊,最近怎么样?
        
        场景2:公园 - 傍晚
        
        小明和小红在公园散步。
        """
    )
    db_session.add(screenplay)
    await db_session.commit()
    await db_session.refresh(screenplay)
    
    yield screenplay
    
    # 清理
    try:
        await db_session.refresh(screenplay)
        await db_session.delete(screenplay)
        await db_session.commit()
    except Exception:
        try:
            await db_session.rollback()
        except Exception:
            pass

3. 路由注册

文件: server/app/api/v1/router.py

添加了缺失的 AI 路由:

from app.api.v1 import (
    # ... 其他导入
    ai_models,
    ai_jobs
)

# 注册路由
api_router.include_router(ai_models.router)
api_router.include_router(ai_jobs.router)

4. 测试用例

实现了 12 个测试用例,覆盖 4 个功能模块:

AI 对话管理 (TestAIConversations)

  • test_create_conversation - 创建 AI 对话
  • test_add_message - 添加对话消息
  • test_mention_resource - @ 提及资源

AI 提示词系统 (TestAIPrompts)

  • test_list_prompts - 获取提示词列表
  • test_get_prompt_by_key - 根据 key 获取提示词

AI 模型查询 (TestAIModels)

  • test_list_models - 获取 AI 模型列表
  • test_filter_models_by_type - 按类型过滤模型

AI 任务管理 (TestAIJobs)

  • test_create_image_job - 创建图片生成任务
  • test_get_job_status - 查询任务状态
  • test_list_user_jobs - 获取用户任务列表

剧本解析 (TestScreenplayParsing)

  • test_parse_screenplay - 剧本解析
  • test_parse_empty_screenplay - 解析空剧本(应该失败)

修复的问题

1. Project fixture 缺少 owner_id

问题: 创建 Project 时未设置 owner_id,违反 NOT NULL 约束

解决方案: 添加 owner_id=test_user.user_id

2. JWT 认证失败 (401)

问题: 系统通过 user_sessions 表验证 token,但测试只生成了 JWT token,未创建 session 记录

解决方案: 在 auth_headers fixture 中创建 UserSession 记录

3. 路由未注册 (404)

问题: ai_modelsai_jobs 路由未在主路由器中注册

解决方案: 在 router.py 中添加路由注册

4. 响应格式不匹配

问题: 测试期望 data["data"]["items"],但实际返回 data["data"] 直接是列表

解决方案: 修改测试断言为 isinstance(data["data"], list)

5. AI Prompts 路由路径

问题: 测试使用 /api/v1/ai/prompts,但实际路由是 /api/v1/admin/ai-prompts

解决方案: 更新测试路径为 /api/v1/admin/ai-prompts

测试运行

# 运行所有 AI 集成测试
docker exec jointo-server-app pytest tests/integration/test_ai_integration.py -v

# 运行特定测试类
docker exec jointo-server-app pytest tests/integration/test_ai_integration.py::TestAIModels -v

# 运行特定测试
docker exec jointo-server-app pytest tests/integration/test_ai_integration.py::TestAIModels::test_list_models -v

当前状态

  • JWT 认证 fixture 已实现
  • 测试 fixtures 已创建
  • 路由已注册
  • ⚠️ 部分测试需要调整响应格式断言
  • ⚠️ 需要验证所有测试用例

下一步

  1. 修复剩余的响应格式断言
  2. 运行完整测试套件
  3. 验证所有测试通过
  4. 添加更多边界情况测试
  5. 添加性能测试

相关文档

技术栈合规性

  • 异步操作 (async/await)
  • pytest-asyncio fixtures
  • 真实 JWT token 生成
  • 数据库 session 管理
  • 测试隔离和清理
  • 符合 jointo-tech-stack 规范