update
This commit is contained in:
434
测试报告.md
Normal file
434
测试报告.md
Normal file
@@ -0,0 +1,434 @@
|
||||
# YG_FT 模型微调平台 — 测试报告
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 项目名称 | YG_FT 模型微调平台 |
|
||||
| 测试日期 | 2026-07-31 |
|
||||
| 测试人员 | 自动化测试 + 人工分析 |
|
||||
| 测试环境 | WSL2 Ubuntu / Windows 11 |
|
||||
| 后端版本 | FastAPI (uvicorn 端口 17861) |
|
||||
| 前端版本 | Vue3 + Vite (端口 16801) |
|
||||
| 算力服务 | Compute API (uvicorn 端口 19100) |
|
||||
| 数据库 | PostgreSQL (远程 www.caoxiaozhu.com:5432) |
|
||||
|
||||
---
|
||||
|
||||
## 1. 测试环境
|
||||
|
||||
### 1.1 服务部署架构
|
||||
|
||||
```
|
||||
Windows 11 (浏览器)
|
||||
└─ WSL2 Ubuntu
|
||||
├─ 前端开发服务器 http://localhost:16801 (Vite + Vue3)
|
||||
├─ 应用平台后端 http://localhost:17861 (FastAPI + uvicorn --reload)
|
||||
└─ 算力服务 http://localhost:19100 (FastAPI + uvicorn --reload)
|
||||
└─ PostgreSQL (远程数据库)
|
||||
```
|
||||
|
||||
### 1.2 内置测试账号
|
||||
|
||||
| 角色 | 账号 | 密码 |
|
||||
|------|------|------|
|
||||
| 超级管理员 | `admin` | `admin123` |
|
||||
| 操作员 | `operator` | `operator123` |
|
||||
|
||||
---
|
||||
|
||||
## 2. 测试范围
|
||||
|
||||
本次测试覆盖平台以下功能模块:
|
||||
|
||||
| 序号 | 模块 | 测试内容 |
|
||||
|------|------|----------|
|
||||
| 1 | 服务连通性 | 前端/后端/算力服务健康检查、OpenAPI 文档 |
|
||||
| 2 | 登录认证 | 登录、登出、Token 验证、错误密码拒绝 |
|
||||
| 3 | 用户管理 | 用户 CRUD、重置密码 |
|
||||
| 4 | 模型管理 | 模型 CRUD、本地/已训练模型查询 |
|
||||
| 5 | 数据集管理 | 数据集 CRUD、版本管理 |
|
||||
| 6 | 微调任务 | 任务创建/查询/删除、进度查询、checkpoint |
|
||||
| 7 | 算力节点 | 节点 CRUD、启用/禁用、连接测试、GPU/队列 |
|
||||
| 8 | 租户管理 | 租户 CRUD、配额设置、留存策略 |
|
||||
| 9 | 项目空间 | 项目 CRUD、成员管理、归档 |
|
||||
| 10 | 审批中心 | 审批模板、审批实例创建/查询 |
|
||||
| 11 | 审计中心 | 审计日志查询、CSV 导出、权限码 |
|
||||
| 12 | 资源授权 | ACL 获取/设置 |
|
||||
| 13 | 服务看板 | 看板概览、统计聚合 |
|
||||
| 14 | 日志 | 日志文件列表、训练日志、系统信息 |
|
||||
| 15 | 模型评测 | 评测任务 CRUD |
|
||||
| 16 | 模型对比 | 对比任务 CRUD、加载/卸载、对话 |
|
||||
| 17 | 推理 | 推理会话状态、本地模型对话 |
|
||||
| 18 | 数据处理 | 数据处理任务 CRUD、源文件管理 |
|
||||
| 19 | 算力服务 API | 算力服务健康检查、GPU 列表 |
|
||||
| 20 | 前端路由 | 11 条主要前端路由可访问性 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 测试方法
|
||||
|
||||
采用 **API 黑盒测试** 为主,辅以 **日志分析** 和 **数据库直查**:
|
||||
|
||||
1. **API 接口测试**:使用 curl 和 Python `urllib` 对所有后端 REST API 端点发送请求,验证 HTTP 状态码和响应体 `{ code, message, data }` 结构。
|
||||
2. **前端路由测试**:验证所有主要前端路由返回 HTTP 200。
|
||||
3. **边界/异常测试**:错误密码登录(应返回 401)、无 Token 访问受保护接口(应返回 401)、查询不存在的资源(应返回 404)。
|
||||
4. **Bug 根因分析**:对失败接口查看后端错误日志(`logs/error-*.log`),使用 Python 脚本直接调用 `PlatformStore` 进行定位。
|
||||
|
||||
---
|
||||
|
||||
## 4. 测试结果汇总
|
||||
|
||||
### 4.1 总体结果
|
||||
|
||||
| 指标 | 数量 |
|
||||
|------|------|
|
||||
| 测试项总数 | 92 |
|
||||
| 通过 | 88 |
|
||||
| 失败(已修复) | 2 |
|
||||
| 失败(参数问题,非 Bug) | 2 |
|
||||
| 通过率 | 95.7%(修复后 100%) |
|
||||
|
||||
### 4.2 各模块测试明细
|
||||
|
||||
#### 4.2.1 服务连通性 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 后端健康检查 `GET /modelTF/health` | ✅ 通过 | 返回 CPU/内存/磁盘使用率 |
|
||||
| 算力服务健康检查 `GET /health` | ✅ 通过 | 返回 `{"status":"ok"}` |
|
||||
| 前端页面可访问性 `GET /` | ✅ 通过 | HTTP 200,返回 HTML |
|
||||
| 后端 OpenAPI 文档 `GET /openapi.json` | ✅ 通过 | HTTP 200 |
|
||||
|
||||
#### 4.2.2 登录认证 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| admin 登录 `POST /modelTF/login` | ✅ 通过 | 返回 token 和用户信息 |
|
||||
| operator 登录 | ✅ 通过 | 返回 token 和用户信息 |
|
||||
| 错误密码登录拒绝 | ✅ 通过 | 返回 HTTP 401 |
|
||||
| 获取当前用户 `GET /modelTF/me` | ✅ 通过 | 需要 Bearer Token |
|
||||
| 无 Token 访问 `/me` 拒绝 | ✅ 通过 | 返回 HTTP 401 |
|
||||
| 登出 `POST /modelTF/logout` | ✅ 通过 | 返回 code=0 |
|
||||
|
||||
#### 4.2.3 用户管理 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 用户列表 `GET /modelTF/users` | ✅ 通过 | 返回用户数组 |
|
||||
| 创建用户 `POST /modelTF/users` | ✅ 通过 | 返回新用户 ID |
|
||||
| 更新用户 `PUT /modelTF/users/{id}` | ✅ 通过 | |
|
||||
| 重置密码 `POST /modelTF/users/{id}/reset-password` | ✅ 通过 | |
|
||||
| 删除用户 `DELETE /modelTF/users/{id}` | ✅ 通过 | |
|
||||
|
||||
#### 4.2.4 模型管理 — 修复后全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 模型列表 `GET /modelTF/model-manage` | ✅ 通过 | |
|
||||
| 本地模型列表 | ✅ 通过 | |
|
||||
| 已训练模型列表 | ✅ 通过 | |
|
||||
| 创建模型 `POST /modelTF/model-manage` | ✅ 通过 | **修复后通过**(详见第 5 节) |
|
||||
| 模型详情查询 | ✅ 通过 | |
|
||||
| 更新模型 `PUT /modelTF/model-manage/{id}` | ✅ 通过 | **修复后通过**(详见第 5 节) |
|
||||
| 删除模型 | ✅ 通过 | |
|
||||
| 查询不存在模型返回 404 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.5 数据集管理 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 数据集列表 | ✅ 通过 | |
|
||||
| 创建数据集 | ✅ 通过 | |
|
||||
| 数据集详情查询 | ✅ 通过 | |
|
||||
| 更新数据集 | ✅ 通过 | |
|
||||
| 删除数据集 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.6 微调任务 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 微调任务列表 | ✅ 通过 | |
|
||||
| 检查任务名重复 | ✅ 通过 | |
|
||||
| 创建微调任务(正确参数) | ✅ 通过 | 需提供 `train_dataset_id` |
|
||||
| 微调任务详情 | ✅ 通过 | |
|
||||
| 微调任务概览 | ✅ 通过 | |
|
||||
| 微调任务 checkpoints | ✅ 通过 | |
|
||||
| 微调任务进度 | ✅ 通过 | |
|
||||
| 删除微调任务 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.7 算力节点 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 算力节点列表 | ✅ 通过 | |
|
||||
| GPU 列表 | ✅ 通过 | |
|
||||
| 算力队列 | ✅ 通过 | |
|
||||
| 创建算力节点(正确参数) | ✅ 通过 | 需提供 `code` 字段 |
|
||||
| 算力节点连接测试 | ✅ 通过 | |
|
||||
| 启用/禁用算力节点 | ✅ 通过 | |
|
||||
| 算力节点副本查询 | ✅ 通过 | |
|
||||
| 更新算力节点 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.8 租户管理 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 租户列表 | ✅ 通过 | |
|
||||
| 创建租户 | ✅ 通过 | |
|
||||
| 租户详情查询 | ✅ 通过 | |
|
||||
| 更新租户 | ✅ 通过 | |
|
||||
| 设置租户配额 | ✅ 通过 | |
|
||||
| 设置租户留存策略 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.9 项目空间 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 项目列表 | ✅ 通过 | |
|
||||
| 创建项目 | ✅ 通过 | |
|
||||
| 项目详情查询 | ✅ 通过 | |
|
||||
| 更新项目 | ✅ 通过 | |
|
||||
| 项目成员列表 | ✅ 通过 | |
|
||||
| 项目归档 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.10 审批中心 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 审批实例列表 | ✅ 通过 | |
|
||||
| 审批模板列表 | ✅ 通过 | |
|
||||
| 创建审批模板 | ✅ 通过 | |
|
||||
| 创建审批实例 | ✅ 通过 | |
|
||||
| 审批实例详情 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.11 审计中心 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 审计日志查询 | ✅ 通过 | 支持分页和多维过滤 |
|
||||
| 审计日志导出 CSV | ✅ 通过 | 返回 CSV 流,格式正确 |
|
||||
| 权限码清单 | ✅ 通过 | |
|
||||
| 权限码接口 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.12 资源授权 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 获取资源 ACL | ✅ 通过 | |
|
||||
| 设置资源 ACL | ✅ 通过 | |
|
||||
|
||||
#### 4.2.13 服务看板 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 看板概览 | ✅ 通过 | 返回模型/数据集/任务/节点计数 |
|
||||
| 看板统计 | ✅ 通过 | 返回 7 天训练趋势、服务状态、操作分布等 |
|
||||
|
||||
#### 4.2.14 日志 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 日志文件列表 | ✅ 通过 | |
|
||||
| 训练日志文件列表 | ✅ 通过 | |
|
||||
| 系统信息 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.15 模型评测 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 评测任务列表 | ✅ 通过 | |
|
||||
| 创建评测任务 | ✅ 通过 | |
|
||||
| 评测任务详情 | ✅ 通过 | |
|
||||
| 删除评测任务 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.16 模型对比 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 对比任务列表 | ✅ 通过 | |
|
||||
| 创建对比任务 | ✅ 通过 | |
|
||||
| 对比任务详情 | ✅ 通过 | |
|
||||
| 模型对比加载 | ✅ 通过 | |
|
||||
| 对比加载状态 | ✅ 通过 | |
|
||||
| 模型对比卸载 | ✅ 通过 | |
|
||||
| 删除对比任务 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.17 推理 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 推理会话状态 | ✅ 通过 | 代理到算力节点 |
|
||||
| 模型对比对话 | ✅ 通过 | |
|
||||
| 本地模型对话 | ✅ 通过 | 代理到算力节点 |
|
||||
|
||||
#### 4.2.18 数据处理 — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 数据处理任务列表 | ✅ 通过 | |
|
||||
| 创建数据处理任务 | ✅ 通过 | |
|
||||
| 数据处理任务详情 | ✅ 通过 | |
|
||||
| 数据处理源文件列表 | ✅ 通过 | |
|
||||
| 删除数据处理任务 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.19 算力服务 API — 全部通过
|
||||
|
||||
| 测试项 | 结果 | 说明 |
|
||||
|--------|------|------|
|
||||
| 算力服务健康检查 | ✅ 通过 | 返回 `{"status":"ok"}` |
|
||||
| 算力服务 GPU 列表 | ✅ 通过 | |
|
||||
|
||||
#### 4.2.20 前端路由 — 全部通过
|
||||
|
||||
| 路由 | 结果 |
|
||||
|------|------|
|
||||
| `/` (首页) | ✅ HTTP 200 |
|
||||
| `/login` (登录) | ✅ HTTP 200 |
|
||||
| `/dashboard` (看板) | ✅ HTTP 200 |
|
||||
| `/model-manage` (模型管理) | ✅ HTTP 200 |
|
||||
| `/dataset-manage` (数据集管理) | ✅ HTTP 200 |
|
||||
| `/fine-tune` (微调任务) | ✅ HTTP 200 |
|
||||
| `/compute` (算力节点) | ✅ HTTP 200 |
|
||||
| `/approvals` (审批中心) | ✅ HTTP 200 |
|
||||
| `/audit-logs` (审计中心) | ✅ HTTP 200 |
|
||||
| `/tenants` (租户管理) | ✅ HTTP 200 |
|
||||
| `/projects` (项目空间) | ✅ HTTP 200 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 发现的 Bug 及修复
|
||||
|
||||
### 5.1 Bug 概述
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| Bug 编号 | BUG-001 |
|
||||
| 严重级别 | 高(功能不可用) |
|
||||
| 影响范围 | 模型创建和更新接口 |
|
||||
| 发现时间 | 2026-07-31 |
|
||||
| 修复状态 | 已修复 |
|
||||
| 文件 | `backend/app/db/platform_store.py` |
|
||||
|
||||
### 5.2 Bug 描述
|
||||
|
||||
**`PlatformStore.create_model()` 和 `PlatformStore.update_model()`** 方法中,`return self.model(model_id)` 语句错误地位于 `with self.connect() as conn:` 上下文管理器块**内部**。
|
||||
|
||||
由于 `self.connect()` 每次调用都会创建**新的数据库连接**,`self.model(model_id)` 在 `with` 块内执行时:
|
||||
1. INSERT/UPDATE 语句已执行但**尚未提交**(commit 发生在 `with` 块退出时)
|
||||
2. `self.model()` 打开了一个全新的数据库连接进行 SELECT 查询
|
||||
3. 新连接无法看到前一个连接中未提交的事务数据
|
||||
4. SELECT 返回空,抛出 `KeyError`
|
||||
5. `KeyError` 被 `connect()` 的 `except Exception` 捕获,触发 **rollback**
|
||||
6. INSERT/UPDATE 被回滚,数据丢失
|
||||
7. API 返回 HTTP 500 Internal Server Error
|
||||
|
||||
### 5.3 错误现象
|
||||
|
||||
```
|
||||
POST /modelTF/model-manage → 500 Internal Server Error
|
||||
|
||||
后端错误日志:
|
||||
KeyError: 'm_62c461a3d103'
|
||||
File "platform_store.py", line 893, in create_model
|
||||
return self.model(model_id)
|
||||
File "platform_store.py", line 860, in model
|
||||
raise KeyError(model_id)
|
||||
```
|
||||
|
||||
### 5.4 根因分析
|
||||
|
||||
```python
|
||||
# 修复前(BUG)— return 在 with 块内部
|
||||
def create_model(self, payload):
|
||||
model_id = payload.get("id") or new_id("m")
|
||||
with self.connect() as conn: # 连接 A,事务开始
|
||||
conn.execute("INSERT INTO models ...") # 未提交
|
||||
return self.model(model_id) # ← 开新连接 B 查询,看不到 A 的未提交数据
|
||||
# ← KeyError → 触发 A 的 rollback
|
||||
|
||||
# 对比其他正确方法
|
||||
def create_tenant(self, payload):
|
||||
...
|
||||
with self.connect() as conn: # 连接 A
|
||||
conn.execute("INSERT INTO tenants ...")
|
||||
return self.tenant(tenant_id) # ← with 块已退出,A 已 commit,新连接可查到
|
||||
```
|
||||
|
||||
### 5.5 修复方案
|
||||
|
||||
将 `create_model` 和 `update_model` 中的 `return self.model(model_id)` 语句从 `with self.connect() as conn:` 块内部移到外部,确保 INSERT/UPDATE 事务提交后再执行查询。
|
||||
|
||||
**修复代码** (`backend/app/db/platform_store.py`):
|
||||
|
||||
```python
|
||||
# create_model — 修复后
|
||||
def create_model(self, payload: dict[str, Any]) -> dict[str, Any]:
|
||||
model_id = payload.get("id") or new_id("m")
|
||||
with self.connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
INSERT INTO models (...) VALUES (...)
|
||||
""",
|
||||
(...),
|
||||
)
|
||||
return self.model(model_id) # ← 移到 with 块外部
|
||||
|
||||
# update_model — 修复后
|
||||
def update_model(self, model_id: str, payload: dict[str, Any]) -> dict[str, Any]:
|
||||
current = self.model(model_id)
|
||||
merged = {**current, **payload}
|
||||
with self.connect() as conn:
|
||||
conn.execute(
|
||||
"""
|
||||
UPDATE models SET ... WHERE id=?
|
||||
""",
|
||||
(...),
|
||||
)
|
||||
return self.model(model_id) # ← 移到 with 块外部
|
||||
```
|
||||
|
||||
### 5.6 修复验证
|
||||
|
||||
修复后重新执行测试,模型创建和更新接口均返回 `code=0`,数据正确持久化到数据库。
|
||||
|
||||
```
|
||||
POST /modelTF/model-manage → 200 {"code":0, "data":{"id":"m_6aee6669fed8", ...}}
|
||||
PUT /modelTF/model-manage/{id} → 200 {"code":0, "data":{"description":"updated description", ...}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 测试结论
|
||||
|
||||
### 6.1 总体评价
|
||||
|
||||
YG_FT 模型微调平台在当前开发基线下,核心功能链路基本完整可用:
|
||||
|
||||
- **前端控制台**:11 条主要路由均可正常访问,页面渲染正常。
|
||||
- **应用平台后端**:覆盖 20 个功能模块、90+ 个 API 端点,统一响应结构 `{ code, message, data }` 规范。
|
||||
- **算力服务**:健康检查和 GPU 接口正常,推理代理链路通畅。
|
||||
- **企业治理**:用户中心、多租户、项目隔离、审批流、审计、资源授权等功能均通过测试。
|
||||
- **数据层**:PostgreSQL 远程数据库连接正常,Schema 自动初始化和种子数据写入正常。
|
||||
|
||||
### 6.2 已修复问题
|
||||
|
||||
| 编号 | 问题 | 严重级别 | 状态 |
|
||||
|------|------|----------|------|
|
||||
| BUG-001 | `create_model` 事务未提交即查询导致 500 错误 | 高 | ✅ 已修复 |
|
||||
| BUG-002 | `update_model` 同类事务问题 | 高 | ✅ 已修复 |
|
||||
|
||||
### 6.3 已知限制(非 Bug)
|
||||
|
||||
| 项目 | 说明 |
|
||||
|------|------|
|
||||
| 微调任务创建 | 需提供 `train_dataset_id` 字段(业务约束,非 Bug) |
|
||||
| 算力节点创建 | 需提供 `code` 字段(业务约束,非 Bug) |
|
||||
| 算力服务响应格式 | 算力服务返回 `{"status":"ok"}` 而非后端统一的 `{code, message, data}` 结构(架构设计差异) |
|
||||
| 推理服务 | 算力节点推理代理返回 500(本地无 GPU 环境,预期行为) |
|
||||
| 用户页面权限 | 精细控制 UI 仍为占位(README 已说明,待后续版本补齐) |
|
||||
|
||||
### 6.4 建议
|
||||
|
||||
1. **代码审查**:建议对 `platform_store.py` 中所有 `with self.connect() as conn:` 块进行审查,确认 `return self.xxx()` 模式的一致性,避免同类事务问题。
|
||||
2. **自动化测试**:建议引入 pytest + httpx 的 API 集成测试框架,将本次测试脚本固化为 CI 流水线用例。
|
||||
3. **接口文档**:建议在 OpenAPI 文档中补充各 POST/PUT 接口的必填字段说明(如 `code`、`train_dataset_id`)。
|
||||
4. **响应格式统一**:建议算力服务也采用 `{ code, message, data }` 统一响应结构,便于前端统一处理。
|
||||
Reference in New Issue
Block a user