Files
john 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
Add TKMind platform extensions, H5/MindSpace stack, and deployment tooling.
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>
2026-06-14 21:30:20 +08:00

278 lines
8.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
sidebar_position: 10
title: 测试要求
sidebar_label: 测试要求
description: Plaza 的自动化测试策略、权限矩阵、E2E 场景、性能基准和验收标准
---
# 测试要求
## 测试策略
```text
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=deletedreply_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
```
### 场景 6SEO 验证
```
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 中
```
### 场景 7publication 下线联动
```
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 调用 |
---
## 前端测试
```bash
# 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 buildui/plaza、ui/ops)— h5-plaza job
□ 后端测试:node --test ui/h5/plaza-*.test.mjs(含 MySQL 集成,CI 提供 MySQL 8 服务)
□ just check-h5-openapi-schemaPlaza/Ops 路由已纳入 ui/h5/openapi.json
□ E2E:core 场景(场景 1-4)— 待 Playwright 落地
□ 新的 SQL 迁移文件可在空库执行(initSchema + plaza-integration 覆盖)
□ 新的 SQL 迁移文件可在含现有数据的库执行(db.mjs ALTER 幂等)
```
本地运行集成测试:
```bash
# 需 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
```