Skip to content

Latest commit

 

History

History
122 lines (97 loc) · 7.3 KB

File metadata and controls

122 lines (97 loc) · 7.3 KB

「鉴微」测试报告

测试遵循约定顺序:① 安全 → ② 性能(两关全过)→ ③ 功能/完整 → ④ 端到端 + 截图。 全程在 Docker dev 环境(LLM_PROVIDER=mockEMBEDDING_PROVIDER=mock)执行,四大模块端到端真集成(API → Redis → Celery Worker → Qdrant / PostgreSQL / MinIO)。

阶段 工具 结果
① 安全 pytest(-m security) + bandit + pip-audit ✅ 9/9 通过;bandit High=0;依赖 CVE 已升级(见 §1.3)
② 性能 tests/perf/run_perf.py(SLA 断言) ✅ 全部达标(搜索 P95 42ms<1s、RAG 首 token 6.7ms<3s)
③ 功能 pytest(-m functional) ✅ 8/8 通过,覆盖四大模块
④ 端到端 Playwright + 截图 见 §4 与 tests/screenshots/

1. 安全测试

1.1 功能性安全用例(pytest -m security)— 9/9 通过

用例 验证点 结果
test_health_ok 健康检查
test_protected_requires_auth 未授权访问受保护接口返回 401(feed/tasks/kb/quota)
test_invalid_token_rejected 伪造 JWT 被拒 401
test_security_headers_present 响应含 X-Content-Type-Options=nosniffX-Frame-Options=SAMEORIGIN
test_password_never_returned 接口不回传口令/哈希
test_tenant_isolation 租户 A 资源对租户 B 不可见、越权删除 404(多租户隔离)
test_free_user_cannot_use_advanced_rag 免费版 RAG 问答被门控 403
test_search_handles_injection_like_input SQL 注入/XSS/路径穿越式输入不致 500
test_login_rate_limited 登录暴力尝试触发 429 限流

1.2 静态安全扫描(bandit)— High = 0

  • 初次扫描发现 1 处 High:hashlib.md5(mock embedding 的 token→维度哈希分桶)。
  • 修复:加 usedforsecurity=False 明确非安全用途。复扫 High=0(残留 3 处 Low 为爬虫 try/except 兜底,属正常防御式代码)。

1.3 依赖 CVE(pip-audit)

依赖 处理
cryptography 43→45 ✅ 清除 CVE-2024-12797
lxml 5→6.1 ✅ 清除 PYSEC-2026-87
markdownify 0.13→0.14.1 ✅ 清除 CVE-2025-46656
starlette→0.47.3(随 FastAPI 0.118) ✅ 清除 CVE-2025-54121(multipart DoS)
残留:cryptography(2026 预警,需 46/48)、starlette(需 1.x,与 FastAPI 不兼容)、pip/pytest(构建/测试工具,非运行时暴露) ⚠️ 已知/带修复路径,待上游兼容版本发布后跟进(不强行大版本跃迁以免破坏栈)

2. 性能测试(SLA 门禁)

tests/perf/run_perf.py 对运行中的服务发压并断言 PRD 四-性能指标,任一不达标即退出非 0、阻断后续功能测试

================ 性能 / SLA 报告 ================
指标                    实测            SLA         结果
health                1.6ms         <200ms      ✅ PASS
search                42.2ms        <1000ms     ✅ PASS   (PRD:语义搜索 <1s)
rag_first_token       6.7ms         <3000ms     ✅ PASS   (PRD:RAG 首 token <3s)
================================================
[perf] 全部达标

说明:mock 供应商下 LLM 时延为本地确定性极小值;真实模型下,语义搜索仍不经 LLM(Qdrant HNSW 召回 + 重排)故稳定 <1s,RAG 首 token 取决于所选模型(方案以"流式先返首 token + 轻量快档 + 召回缓存"保障 <3s)。


3. 功能 / 完整测试(pytest -m functional)— 8/8 通过,覆盖率 59%

用例 覆盖模块 / PRD 结果
test_feed_refresh_and_list 资讯流抓取→时间轴列表(字段:中文精要/英文标题/留源URL) 2.1
test_feed_favorite_into_kb 收藏→入库"AI资讯"分类,不占配额逻辑 2.1.4
test_analyze_github GitHub 深度解剖→报告入库(开源项目分类、可读内容) 2.2
test_analyze_site_md 站点熔炼→中文 MD 生成入库 2.3
test_analyze_quota_enforced_for_free 免费版每月 3 次解析配额护栏 六-商业化
test_upload_and_tagging 文档上传→解析→自动打标(Tag/摘要/分类) 2.4.1/2.4.2
test_semantic_search 全局语义搜索召回命中分块 2.4.3
test_rag_chat_with_citations RAG 流式问答帧(token/citations/done 或 not_found 防幻觉) 2.4.4

覆盖率 59%:worker 任务代码在独立 worker 容器执行,覆盖率仅统计 api/测试进程,故 worker/* 行覆盖偏低,但功能测试已端到端证明其正确路径。


4. 端到端 + 截图(Playwright)

经 Caddy(http://localhost)访问真实前端(Vite)+ 真实后端,API 预置数据后逐屏截图,产物在 tests/screenshots/

截图 画面
01-login.png 登录/注册(铜镜深色)
02-feed.png 见微 · 资讯流(发光时间轴 + 卡片瀑布流)
03-github-report.png 知著 · GitHub 深度解剖报告(档案卡 + 目录 + 正文)
04-site.png 重构 · 站点熔炼三栏阅读
05-kb.png 鉴真 · 知识库(树状导航 + 网盘式文档)
06-search.png / 07-rag.png 语义搜索结果 / RAG 引用问答

4.1 执行记录

Running 6 tests using 1 worker
  ok 1  01 登录页 (2.3s)
  ok 2  02 资讯流(见微) (3.0s)
  ok 3  03 GitHub 深度解剖(知著) (3.0s)
  ok 4  04 站点熔炼(重构) (2.6s)
  ok 5  05 知识库(鉴真) (2.4s)
  ok 6  06 语义搜索 + RAG (7.9s)
  6 passed (27.5s)

产物(tests/screenshots/,均为真实「铜镜」UI + 真实预置数据,非空白): 01-login.png(137KB) · 02-feed.png(68KB) · 03-github-report.png(71KB) · 04-site.png(48KB) · 05-kb.png(67KB) · 06-search.png(78KB) · 07-rag.png(78KB)

要点核对(目视):登录页铜镜深色 + 赤金 CTA + 四模块文案;资讯流发光时间轴 + 卡片(赤金"最新"角标/中文精要/英文原题/留源);GitHub 报告档案卡 + 目录 + 正文;知识库 Notion 树导航 + 标签筛选 + Pro 配额条 + 顶部 RAG 对话框(水波纹"检索中" + 赤金引用提示) + 网盘式文档列表。


5. 测试过程中发现并修复的缺陷(节选)

# 现象 根因 修复
1 register/login 返回 422(body 被当 query) slowapi @limiter.limit 装饰器破坏 FastAPI 签名 改为自写限流依赖 Depends(rate_limit(...))
2 测试 "Event loop is closed" pytest 多事件循环复用全局异步连接池 测试进程 DB 用 NullPool、Redis 每次新建
3 注册 tenant_id NOT NULL 违约 flush 后才设 tenant_id 注册时显式生成 id 并一并赋 tenant_id
4 bandit High(md5) 哈希分桶被判安全用途 usedforsecurity=False
5 前端报告永不加载 前后端任务状态枚举漂移(success vs succeeded) 前端兼容 success
6 RAG/搜索 worker "different loop" / async-with 不支持 全局 AsyncQdrantClient 跨循环 + 版本不支持 async with 本地客户端 + try/finally await close()
7 worker 任务 DB/Redis "different loop" asyncio.run 每任务新循环 worker 用常驻后台事件循环跑协程
8 doc_tags 外键违约 同事务父子表插入顺序 插 Document 后 flush 再插 DocTag