4e21ca937a
Deploy Documentation / deploy (push) Has been cancelled
Canary / Prepare Version (push) Has been cancelled
Canary / build-cli (push) Has been cancelled
Canary / Upload Install Script (push) Has been cancelled
Canary / bundle-desktop (push) Has been cancelled
Canary / bundle-desktop-intel (push) Has been cancelled
Canary / bundle-desktop-linux (push) Has been cancelled
Canary / bundle-desktop-windows (push) Has been cancelled
Canary / bundle-desktop-windows-cuda (push) Has been cancelled
Canary / Release (push) Has been cancelled
Unused Dependencies / machete (push) Has been cancelled
CI / changes (push) Has been cancelled
CI / Check Rust Code Format (push) Has been cancelled
CI / Build and Test Rust Project (push) Has been cancelled
CI / Build Rust Project on Windows (push) Has been cancelled
CI / Check MSRV (push) Has been cancelled
CI / Lint Rust Code (push) Has been cancelled
CI / Check Generated Schemas are Up-to-Date (push) Has been cancelled
CI / Test and Lint Electron Desktop App (push) Has been cancelled
CI / H5 Plaza Tests and Build (push) Has been cancelled
Live Provider Tests / check-fork (push) Has been cancelled
Live Provider Tests / changes (push) Has been cancelled
Live Provider Tests / Build Binary (push) Has been cancelled
Live Provider Tests / Smoke Tests (push) Has been cancelled
Live Provider Tests / Smoke Tests (Code Execution) (push) Has been cancelled
Live Provider Tests / Compaction Tests (push) Has been cancelled
Live Provider Tests / goose server HTTP integration tests (push) Has been cancelled
Publish Ask AI Bot Docker Image / docker (push) Has been cancelled
Publish Docker Image / docker (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
Fork goose with custom MCP widgets, platform extensions (aider, git, web, search), MindSpace H5 backend/frontend, Plaza/Ops UIs, and deploy scripts for tkmind.cn. Co-authored-by: Cursor <cursoragent@cursor.com>
8.4 KiB
8.4 KiB
sidebar_position, title, sidebar_label, description
| sidebar_position | title | sidebar_label | description |
|---|---|---|---|
| 10 | 测试要求 | 测试要求 | Plaza 的自动化测试策略、权限矩阵、E2E 场景、性能基准和验收标准 |
测试要求
测试策略
E2E 测试(Playwright) 覆盖核心用户流程
│
集成测试(真实 DB + Redis) 覆盖 API 契约和权限矩阵
│
单元测试 覆盖热度算法、格式化函数、状态机
所有测试必须使用真实数据库连接,不允许 Mock DB(与 MindSpace 测试策略一致)。
权限矩阵
每个 API 必须测试以下角色的访问结果:
| 接口 | 游客 | 普通用户(非作者) | 作者本人 | 运营人员 |
|---|---|---|---|---|
| GET /feed | 200 ✅ | 200 ✅ | 200 ✅ | 200 ✅ |
| GET /posts/:id | 200 ✅ | 200 ✅ | 200 ✅ | 200 ✅ |
| POST /posts(发布到广场) | 401 ❌ | 200 ✅ | 200 ✅ | 200 ✅ |
| DELETE /posts/:id | 401 ❌ | 403 ❌ | 200 ✅ | - |
| POST /posts/:id/reactions | 401 ❌ | 200 ✅ | 200 ✅ | 200 ✅ |
| POST /posts/:id/comments | 401 ❌ | 200 ✅ | 200 ✅ | 200 ✅ |
| DELETE /comments/:id(他人评论) | 401 ❌ | 403 ❌ | 403 ❌ | - |
| DELETE /comments/:id(自己评论) | 401 ❌ | 200 ✅ | 200 ✅ | - |
| POST /users/:slug/follow(关注自己) | 401 ❌ | - | 422 ❌ | - |
| POST /ops/review/posts/:id | 401 ❌ | 403 ❌ | 403 ❌ | 200 ✅ |
| GET /ops/analytics | 401 ❌ | 403 ❌ | 403 ❌ | 200 ✅ |
必测 API 场景
发布到广场
✅ 正常发布:publication online → 创建 plaza_posts status=pending_review
✅ publication 不是 online 状态 → 422 PUBLICATION_NOT_ONLINE
✅ 同一 publication 重复 POST → 409 ALREADY_PUBLISHED
✅ 同一 publication 更新元数据 → PATCH /posts/:id 成功
✅ publication 归属其他用户 → 403
✅ 用户被封禁发帖权限 → 403 POST_PERMISSION_DENIED
✅ 下线 publication 后,对应 plaza_posts status 自动变为 hidden
Feed 接口
✅ 默认返回 hot 排序
✅ sort=new 返回按 published_at 倒序
✅ 按 category slug 筛选只返回该分类帖子
✅ 游客请求 viewer_reacted 字段为 null
✅ 登录用户请求 viewer_reacted 正确反映点赞/收藏状态
✅ status=pending_review 和 hidden 的帖子不出现在 feed 中
✅ 游标翻页不重复、不遗漏
点赞
✅ 点赞成功 → plaza_posts.like_count +1(经 Redis → MySQL 同步后)
✅ 重复点赞 → 幂等,返回 200,计数不重复增加
✅ 取消点赞 → 计数 -1,不出现负数
✅ 取消未点赞的帖子 → 404 或 204(幂等)
评论
✅ 发表一级评论 → comment_count +1
✅ 发表二级回复 → 父评论 reply_count +1
✅ 三级嵌套(parent_id 指向二级评论)→ 422 REPLY_DEPTH_EXCEEDED
✅ 对关闭评论的帖子发评论 → 422 COMMENT_DISABLED
✅ 评论超过 500 字符 → 422
✅ 软删除评论 → content 为空,status=deleted,reply_count 保留
✅ 帖子删除(status=hidden)后,已有评论不暴露给公开接口
关注
✅ 关注他人 → follower_count / following_count 各 +1(事务内)
✅ 取消关注 → -1
✅ 关注自己 → 422 SELF_FOLLOW
✅ 重复关注 → 幂等返回 200,计数不重复
运营审核
✅ 审核通过 → status=published,写入 ops_audit_log
✅ 拒绝 → status=rejected,必须有 reason,发送通知
✅ 隐藏 → status=hidden,帖子从 feed 消失
✅ 普通用户调用审核接口 → 403 OPS_PERMISSION_DENIED
✅ 审核日志不可修改(不提供 UPDATE/DELETE 接口)
热度算法测试
✅ 新帖 hot_score = 0(无互动,发布即刻)
✅ 相同互动量、发布时间越早 hot_score 越低(时间衰减验证)
✅ 修改 plaza_algorithm_config 权重后,下次计算周期生效
✅ hot_score 不出现负数
✅ 大量帖子(1000 条)批量计算完成时间 < 5 秒
数据一致性测试
✅ 配额预留和确认在同一事务(从 MindSpace 继承,无需新测)
✅ 关注关系表 UNIQUE 约束:并发关注不产生重复行
✅ 点赞 UNIQUE 约束:并发点赞不超过 1 条记录
✅ 发布到广场 UNIQUE(publication_id):并发请求不产生重复帖子
✅ publication 下线事务:plaza_posts 同步隐藏在同一事务内完成
E2E 场景(Playwright)
场景 1:完整发布流程
1. 用户 A 登录 MindSpace
2. 发布一个 MindSpace 页面(publication online)
3. 点击「发布到广场」
4. 选择分类「职场报告」,输入标签「复盘」
5. 确认发布
6. 验证:/plaza 首页最新列表出现该帖子
7. 验证:curl /plaza/p/{id} 的 HTML 包含帖子标题(SSR 验证)
场景 2:互动完整流程
1. 游客打开帖子详情 /plaza/p/{id}
2. 点击点赞 → 弹出登录引导浮层
3. 游客登录
4. 登录后自动回到帖子详情,点赞成功
5. 刷新页面,点赞状态保持(viewer_reacted.liked = true)
6. 点击取消点赞,状态恢复
场景 3:评论和回复
1. 用户 A 在帖子下发表评论「很好!」
2. 用户 B 登录后回复「+1」
3. 验证:评论区展示 A 的评论,B 的回复在其下方
4. A 删除自己的评论
5. 验证:评论显示「该评论已删除」,B 的回复仍然可见
6. 尝试三级嵌套 → 前端禁用回复按钮
场景 4:运营审核
1. 用户发布帖子到广场,status=pending_review
2. 游客访问 /plaza,该帖子不可见
3. 运营人员登录 /ops/review
4. 点击「通过」审核
5. 验证:帖子在广场首页可见
6. 验证:ops_audit_log 有一条记录
场景 5:越权访问
1. 用户 A 发布帖子到广场
2. 用户 B 尝试 DELETE /api/plaza/v1/posts/{A的帖子id}
3. 验证:返回 403
4. 用户 B 尝试发布用户 A 的 publication → 返回 403
5. 游客尝试发表评论 → 返回 401
场景 6:SEO 验证
1. 发布一个帖子到广场
2. curl -A "Googlebot" https://go.tkmind.cn/plaza/p/{id}
3. 验证响应 HTML 中包含:
- <title> 标签含帖子标题
- <meta property="og:title">
- <meta property="og:image">
- <meta property="og:description">
- <script type="application/ld+json"> Article schema
4. curl https://go.tkmind.cn/sitemap.xml
5. 验证帖子 URL 出现在 sitemap 中
场景 7:publication 下线联动
1. 帖子在广场正常展示(status=published)
2. 作者在 MindSpace 将 publication 下线
3. 验证:plaza_posts.status 自动变为 hidden
4. 验证:/plaza feed 中该帖子消失
5. 验证:直接访问 /plaza/p/{id} 返回 404
性能基准
在测试环境(单机 2C4G)满足:
| 接口 | p50 | p99 | 说明 |
|---|---|---|---|
| GET /feed(第一页,冷缓存) | < 200ms | < 500ms | MySQL 查询 |
| GET /feed(命中 Redis 缓存) | < 30ms | < 100ms | 缓存读取 |
| GET /posts/:id | < 100ms | < 300ms | |
| POST /posts/reactions | < 100ms | < 300ms | Redis INCR |
| POST /posts/comments | < 150ms | < 400ms | MySQL 写入 |
| 热度计算(1000 帖子) | < 5s | - | 定时任务 |
| Next.js SSR(帖子详情) | < 300ms | < 800ms | 含 API 调用 |
前端测试
# Plaza Next.js
cd ui/plaza
pnpm test # Jest 单元测试
pnpm e2e # Playwright E2E
# 测试文件位置
ui/plaza/__tests__/
api.test.ts # API 封装函数测试
format.test.ts # 数字格式化测试
algorithm.test.ts # hot_score 公式验证(前端展示用)
ui/plaza/e2e/
publish-flow.spec.ts # 发布完整流程
interaction.spec.ts # 互动场景
seo.spec.ts # SSR 和 meta 验证
CI 检查清单
每个 PR 合并前 CI 必须通过:
□ pnpm build(ui/plaza、ui/ops)— h5-plaza job
□ 后端测试:node --test ui/h5/plaza-*.test.mjs(含 MySQL 集成,CI 提供 MySQL 8 服务)
□ just check-h5-openapi-schema(Plaza/Ops 路由已纳入 ui/h5/openapi.json)
□ E2E:core 场景(场景 1-4)— 待 Playwright 落地
□ 新的 SQL 迁移文件可在空库执行(initSchema + plaza-integration 覆盖)
□ 新的 SQL 迁移文件可在含现有数据的库执行(db.mjs ALTER 幂等)
本地运行集成测试:
# 需 MySQL(或 CI 同款环境变量)
export MYSQL_HOST=127.0.0.1 MYSQL_USER=root MYSQL_PASSWORD=... MYSQL_DATABASE=...
cd ui/h5 && node --test plaza-integration.test.mjs