测试用例补充并修复问题

This commit is contained in:
nojava
2026-05-18 21:54:13 +08:00
parent 2134ef4691
commit c6d1b54822
16 changed files with 1694 additions and 470 deletions
+299 -429
View File
@@ -1,478 +1,348 @@
# Jog System 自动化测试计划
# Jog System 自动化测试规范(AI 测试用例唯一输入)
| 项目 | 内容 |
> **更新**:需求级**全量展开**且文件名含 Cursor 的单一输入见 [`jog-system-cursor-automated-test-spec.md`](jog-system-cursor-automated-test-spec.md)。本文档保留为精简版路由与执行现状摘要。
| 属性 | 内容 |
| :--- | :--- |
| 文档版本 | V1.0 |
| 文档版本 | V2.0 |
| 生成日期 | 2026-05-18 |
| 适用范围 | Jog System 后端 Maven 多模块、Vue 3 前端、数据库迁移与部署验证 |
| 测试目标 | 建立可持续运行的自动化测试体系,覆盖核心业务、接口契约、安全控制、前端流程和发布质量门禁 |
| 用途 | **仅依赖本文档**即可推导可执行的自动化测试用例(单元 / 集成 / 契约 / E2E / 安全 / 性能冒烟);业务验收口径同时映射需求文档中的 AC 编号 |
| 仓库实际模块名 | `jog-common``jog-framework``jog-module-system``jog-module-blog``jog-module-comment``jog-admin``jog-frontend` |
| 技术栈摘要 | 后端 Spring Boot 3.4.x、Java 21、Spring Security + JWT、MyBatis-Plus、MySQL、Redis、Flyway、SpringDoc;前端 Vue 3、Vite 6、Element Plus、Pinia、Axios |
> **说明**:历史文档 `jog-system-technical-design.md` 中的路径示例(如 `/api/app/blog/articles`)与当前代码不一致时,**以本文档「附录 A」为准**(来自当前 Controller 扫描)。需求规格中以 `AC-*` 编号的验收场景,在「第 7 节」逐条映射到可自动化用例骨架。
---
## 1. 项目扫描结论
## 1. 当前已执行的测试与验证(事实记录)
### 1.1 技术与模块
以下内容来自对仓库的一次质量核验(详见 `doc/jog-system-bug-list.md`),代表**截至文档日期的真实执行状況**,而非目标态。
本项目为前后端分离的博客系统:
### 1.1 已执行项
- 后端:Spring Boot 3.4.5、Java 21、Maven 多模块、Spring Security + JWT、MyBatis-Plus、MySQL、Redis、Flyway、SpringDoc OpenAPI。
- 前端:Vue 3.5、Vite 6、Element Plus、Pinia、Vue Router、Axios、Tiptap。
- 模块结构:
- `jog-common`:统一响应、分页模型、异常、枚举、限流注解等公共能力。
- `jog-framework`:安全配置、JWT、鉴权过滤器、XSS 过滤、限流切面、全局异常。
- `jog-module-system`:登录、注册、用户信息、管理员用户管理。
- `jog-module-blog`:文章、分类、标签、点赞、公开列表、后台文章管理。
- `jog-module-comment`:评论、回复、点赞、审核、后台评论管理。
- `jog-admin`:启动入口、应用配置、Flyway 数据库迁移。
- `jog-frontend`:前台浏览、登录注册、个人中心、文章编辑、后台管理页面。
| 序号 | 类别 | 命令或方式 | 结果摘要 |
| :---: | :--- | :--- | :--- |
| T-01 | 后端编译链路 | `mvn -B test` | Maven 生命周期通过;**各模块均无自有 `src/test`Surefire 报告为 `No tests to run`**(无 JUnit 级自动化回归) |
| T-02 | 前端生产构建 | `jog-frontend``npm run build` | **Node v16.20.2**Vite 报错 `crypto.getRandomValues is not a function`,构建失败。**Node v24.15.0**:构建通过,产物按项目配置输出到 `jog-admin/src/main/resources/static` |
| T-03 | 前端依赖与脚本 | `package.json` | 仅有 `dev` / `build` / `preview`**无** `test:unit``test:e2e`、lint 脚本 |
| T-04 | API 契约(静态) | 人工对比 `jog-frontend/src/api/*.js` 与后端 Controller | 曾发现路径/方法不一致;经修复后应以附录 A 与 OpenAPI 重新做**双向校验**(当前未纳入 CI 自动化) |
| T-05 | 数据库映射(静态) | 对比实体 `@TableName` / `@TableField` 与 Flyway `V1__init_schema.sql` | 曾发现表名、字段不一致;修复记录见 BUG-003/BUG-004**仍需带库集成测试**验证) |
| T-06 | 安全配置(静态) | 对比 `JwtTokenProvider`、JWT 过滤器、`SecurityConfig` 与 Controller 前缀 | 曾发现角色 Claims、未保护路径等问题;部分已修复(见 BUG-005/006/007),**需自动化权限矩阵回归** |
### 1.2 当前测试基础
### 1.2 明确未执行 / 缺失项
- 后端仅 `jog-admin` 显式引入 `spring-boot-starter-test`,其余业务模块未单独声明测试依赖。
- 项目源码中未发现自有 `src/test` 测试目录。
- 前端 `package.json` 当前仅包含 `dev``build``preview`,未配置单元测试、组件测试、E2E 测试或 lint 脚本。
- `node_modules` 已存在于工作区,属于依赖产物,不纳入源码测试范围。
### 1.3 扫描发现的测试重点
- 后端 Controller 实际路径为 `/api/auth``/api/article``/api/comment``/api/admin/**``/api/public/**` 等。
- 前端 API 封装中存在 `/api/public/user/login``/api/app/article/mine``/api/app/comment/**` 等路径,与当前后端 Controller 的部分路径不一致,应将“前后端接口契约一致性”列为首要自动化检查。
- `SecurityConfig``/api/admin/**` 需要 `ADMIN` 角色,`/api/app/**` 需要 `USER``ADMIN`,但部分业务 Controller 未挂在 `/api/app` 下,需通过安全回归测试确认实际权限边界。
- `application.yml` 中含真实数据库、Redis 地址和密码样式配置,测试环境应改用隔离配置与环境变量,禁止自动化测试直接访问生产或公网中间件。
- 需求文档与当前代码实现存在差异,例如验证码、邮箱验证、多端会话上限、评论三级嵌套、图片上传、关注、通知、标签管理等能力并未完整落地,自动化测试应区分“已实现回归”和“需求缺口验证”。
---
## 2. 测试目标与质量门禁
### 2.1 测试目标
- 保证登录、注册、文章发布、文章浏览、点赞、评论、后台审核、分类和用户管理等核心链路稳定。
- 保证 JWT 鉴权、角色权限、Token 刷新/登出、限流、XSS 防护、统一异常响应可持续回归。
- 保证前后端 API 路径、请求方法、请求参数、响应结构一致。
- 保证 Flyway 迁移脚本、实体映射、MyBatis-Plus 逻辑删除与分页查询可靠。
- 保证前端路由守卫、表单校验、Axios 拦截器和关键页面交互可回归。
### 2.2 推荐质量门禁
| 阶段 | 必跑项 | 通过标准 |
| :--- | :--- | :--- |
| 本地提交前 | 后端单元测试、前端构建、前端单元测试 | 全部通过,无新增严重告警 |
| 合并请求 | 后端集成测试、API 契约测试、前端组件测试、E2E 冒烟 | 全部通过,核心模块覆盖率达标 |
| 发布前 | 全量 E2E、迁移脚本验证、安全回归、性能冒烟 | P0/P1 缺陷为 0,P2 有明确处理计划 |
| 上线后 | 健康检查、核心链路巡检、日志错误扫描 | 首页/API/登录/发文/评论均可用 |
### 2.3 覆盖率目标
| 层级 | 建议目标 |
| 序号 | 说明 |
| :--- | :--- |
| 后端 Service 单元测试 | 行覆盖率 >= 80%,分支覆盖率 >= 70% |
| 后端 Controller/API 测试 | 核心接口 100% 覆盖,错误路径至少覆盖主要业务错误码 |
| 安全与鉴权测试 | 所有公开、登录、普通用户、管理员接口权限矩阵 100% 覆盖 |
| 前端工具/API/Store 单元测试 | 行覆盖率 >= 70% |
| 前端关键页面组件测试 | 登录、注册、首页、详情、编辑器、后台列表页面全覆盖 |
| E2E 测试 | 核心用户旅程 100% 覆盖,非核心后台功能冒烟覆盖 |
| N-01 | **无任何** `src/test/java` 下的单元测试或集成测试(仓库扫描为 0 个测试类) |
| N-02 | **无** Vitest / Playwright / Cypress 等前端或 E2E 套件 |
| N-03 | **无** CI 中可重复的契约 diffOpenAPI vs `src/api`)流水线步骤 |
---
## 3. 测试分层策略
## 2. 测试目标与质量门禁(目标态)
### 3.1 后端单元测试
### 2.1 目标
推荐工具:JUnit 5、Mockito、AssertJ、Spring Security Test
- 核心链路:认证、注册、Token 刷新、文章 CRUD 与列表、评论、分类/标签、后台用户管理与审核
- 横切能力:JWT 鉴权、角色(`ROLE_ADMIN` / `ROLE_USER`)、统一响应 `ApiResult`、分页 `PageResult`、限流、`XssFilter`、Flyway 迁移可重复执行。
- **前后端契约**:HTTP 方法、路径、请求/响应 JSON 字段与前端封装一致。
- **需求对齐**:凡本文档标记为 `(需求)` 的用例,应以 `doc/jog-system-requirements.md` 中同名 AC 为判定依据;标记为 `(实现差异)` 的,以当前代码为准并建议产品确认。
重点覆盖:
### 2.2 建议门禁(落地后)
- `AuthServiceImpl`
- 邮箱不存在、密码错误、账号锁定、登录成功。
- 管理员登录的角色校验。
- 注册邮箱唯一性、密码加密、默认用户状态。
- Refresh Token 校验失败、用户不存在、刷新成功。
- 登出时 Token 加入黑名单。
- `UserServiceImpl`
- 当前用户信息查询。
- 用户列表分页、状态筛选。
- 管理员重置密码、锁定/解锁用户。
- `ArticleServiceImpl`
- 创建草稿/发布文章、发布时间设置。
- 更新文章、标签重建、作者权限校验。
- 公开列表分页、分类/标签/关键词过滤。
- 我的文章、后台文章列表。
- 回收站、恢复、作者删除、管理员删除。
- 浏览量递增、点赞/取消点赞、文章不存在。
- `CategoryServiceImpl`
- 分类创建、重名、更新、删除。
- 启用分类列表排序。
- `CommentServiceImpl`
- 创建根评论和回复。
- 父评论不存在、回复层级限制。
- 评论列表根评论与回复排序。
- 作者删除权限、管理员审核、点赞/取消点赞。
- `RateLimitAspect``JwtTokenProvider``TokenBlacklistService``XssFilter`
- 限流 Key 与过期时间。
- Token 生成、解析、过期、非法签名。
- 黑名单命中。
- 常见 XSS payload 过滤。
### 3.2 后端集成测试
推荐工具:Spring Boot Test、MockMvc、TestcontainersMySQL、Redis)、Flyway、spring-security-test。
重点覆盖:
- 使用 Testcontainers 启动隔离 MySQL/Redis,运行 Flyway 迁移。
- 验证 `V1__init_schema.sql``V2__init_data.sql` 可重复初始化干净环境。
- 验证实体 `@TableName` 与实际表名一致,重点关注 `sys_user`/`blog_article` 等表与代码实体映射。
- 验证 MyBatis-Plus 分页插件、逻辑删除字段、唯一索引冲突、事务回滚。
- 使用 MockMvc 对 Controller 执行端到端接口测试,断言 HTTP 状态、统一响应结构、业务错误码和数据库副作用。
### 3.3 API 契约测试
推荐工具:SpringDoc OpenAPI 导出、Schemathesis 或 Dredd、Postman/Newman、或自定义 OpenAPI diff。
契约测试必须覆盖:
- 后端 OpenAPI 与前端 `src/api/*.js` 中路径、方法、参数一致。
- 统一响应结构 `ApiResult` 字段稳定:`code``message``data`
- 分页响应 `PageResult` 字段稳定:列表、总数、页码、页大小。
- 401、403、429、业务异常响应格式一致。
- Token 刷新接口路径一致。当前前端调用 `/api/public/refresh-token`,后端扫描到的是 `/api/auth/refresh`,需优先纳入失败用例。
### 3.4 前端单元与组件测试
推荐工具:Vitest、Vue Test Utils、jsdom、MSW、Testing Library。
重点覆盖:
- `utils/request.js`
- 请求自动附加 `Authorization`
- 业务 `code !== 200` 的错误处理。
- 401 清理本地 Token 并跳转登录。
- 403、429、网络错误提示。
- Token 刷新失败/成功后的重试逻辑。
- `router/index.js`
- 未登录访问 `/app/**``/admin/**` 跳转登录。
- 登录后路由放行。
- 页面标题设置。
- 管理员路由需要补充前端角色校验测试;当前代码只检查 token,未检查 `requiresAdmin`
- 页面组件
- `Login.vue``Register.vue`:表单校验、提交状态、错误提示、登录后跳转。
- `Home.vue`:列表加载、分页、分类筛选、空状态。
- `ArticleDetail.vue`:详情渲染、评论列表、点赞、评论提交。
- `ArticleEditor.vue`:标题/内容校验、草稿/发布、分类标签选择、编辑回填。
- 后台 `Users.vue``Articles.vue``Comments.vue``Categories.vue`:列表、筛选、分页、操作确认。
### 3.5 E2E 测试
推荐工具:Playwright。
建议用户旅程:
1. 访客打开首页,查看公开文章列表,进入文章详情。
2. 新用户注册、登录、进入个人控制台。
3. 用户创建草稿、发布文章、编辑文章、移入回收站、恢复文章、删除文章。
4. 另一用户浏览文章、点赞文章、发表评论、回复评论、取消点赞。
5. 管理员登录后台,查看用户列表、重置密码、锁定用户。
6. 管理员查看文章列表、删除违规文章。
7. 管理员查看评论列表、审核评论、删除评论。
8. 分类创建、编辑、删除后,前台筛选结果同步变化。
9. 未登录用户访问编辑页会被重定向到登录页,并在登录后返回原目标页。
10. 普通用户尝试访问后台应被拒绝。
### 3.6 安全自动化测试
重点用例:
- JWT
- 缺失 Token、伪造 Token、过期 Token、黑名单 Token。
- 用户 Token 访问管理员接口返回 403。
- 管理员 Token 访问后台接口成功。
- 限流
- 登录 60 秒内超过 5 次被限制。
- 注册 1 小时内超过 3 次被限制。
- 限流 Key 应区分 IP/用户/接口,避免全局误伤。
- XSS
- 文章和评论中提交 `<script>`、事件属性、`javascript:` 链接。
- 富文本合法标签不应被过度清洗。
- CORS/CSRF
- CORS 允许策略在生产环境应收敛,自动化检查不允许 `*` 与凭证同时进入生产配置。
- CSRF 已关闭,需确认仅用于 JWT 无状态 API。
- 敏感信息
- 扫描配置文件中数据库密码、Redis 密码、JWT 密钥、邮箱密码。
- 自动化测试禁止连接 `application.yml` 中公网数据库和 Redis。
### 3.7 性能与可靠性测试
推荐工具:k6、JMeter 或 Gatling。
冒烟指标:
- 首页文章列表 P95 < 500ms。
- 文章详情 P95 < 500ms。
- 登录接口 P95 < 800ms。
- 创建文章 P95 < 1000ms。
- 评论列表 P95 < 500ms。
- 50 并发用户下错误率 < 1%。
专项场景:
- 高频浏览文章详情时浏览量更新是否产生锁竞争或丢失更新。
- 点赞/取消点赞并发操作是否出现负数计数或唯一索引冲突。
- 评论列表在大量回复下的 N+1 查询问题。
- 后台文章/评论/用户分页在万级数据下的响应时间。
---
## 4. 测试环境规划
### 4.1 环境分层
| 环境 | 用途 | 数据策略 |
| :--- | :--- | :--- |
| Local | 开发者快速回归 | H2 或 Testcontainers,测试结束自动销毁 |
| CI | 合并请求质量门禁 | Testcontainers MySQL/Redis,固定种子数据 |
| Staging | 发布前全量验证 | 与生产拓扑接近,脱敏数据 |
| Prod Smoke | 上线后巡检 | 只执行只读或专用测试账号的轻量用例 |
### 4.2 测试配置要求
- 新增 `application-test.yml`,数据库和 Redis 全部来自 Testcontainers 或本地隔离实例。
- Flyway 在测试环境启用,保证迁移脚本真实可用。
- 禁止测试代码读取公网数据库地址、真实 Redis 密码、真实 SMTP。
- 测试账号和测试文章使用固定前缀,例如 `auto_test_`,便于清理。
- 前端 E2E 使用独立 `.env.test`,指向测试后端。
---
## 5. 测试数据设计
### 5.1 基础数据
| 类型 | 数据 |
| 阶段 | 必跑项 |
| :--- | :--- |
| 管理员 | `admin@example.com`,角色 ADMIN |
| 普通用户 A | `user_a@example.com`,角色 USER |
| 普通用户 B | `user_b@example.com`,角色 USER |
| 锁定用户 | `locked@example.com`,状态 LOCKED |
| 分类 | 技术、生活、公告 |
| 标签 | Java、Vue、测试、随笔 |
| 文章 | 草稿、公开已发布、私密、回收站、已删除 |
| 评论 | 根评论、一级回复、待审核、已屏蔽、已删除 |
| 本地/PR | `mvn -B verify`(含单测+集成)、前端 `npm run build``npm run test:unit`、OpenAPI↔前端 API 契约检查 |
| 发布前 | Testcontainers 集成测试全绿、核心 Playwright 冒烟、Flyway 干净库迁移 |
| 上线后 | 部署清单 `doc/jog-system-deployment-checklist.md` 第 11 节选段自动化或半自动巡检 |
### 5.2 边界数据
### 2.3 覆盖率期望(指导 AI 分优先级)
- 标题空、标题 200 字、标题 201 字
- 密码长度 5、6、20、21
- 评论内容空、1000 字、超过 1000 字
- 分页 `page=0``page=1``pageSize=1``pageSize=100``pageSize=101`
- 不存在的用户 ID、文章 ID、评论 ID、分类 ID。
- 重复邮箱、重复分类名、重复点赞。
- 富文本中包含合法 HTML、XSS payload、超长内容。
- 后端:Service 核心分支优先;Controller/MockMvc 覆盖所有附录 A 中带「写操作」或「鉴权敏感」的接口
- 前端:`utils/request.js`Token、401/403/429)、`router``requiresAuth` / `requiresAdmin`)、各业务 `src/api/*.js`
- E2E:访客可读、用户发文与评论、管理员审核与删文的最短路径
---
## 6. 自动化用例清单
## 3. 测试环境与数据约定
### 6.1 认证与用户
### 3.1 运行时版本
| 编号 | 类型 | 场景 | 预期 |
| :--- | :--- | :--- | :--- |
| AUTH-001 | 单元/API | 正确邮箱密码登录 | 返回 accessToken、refreshToken、用户信息 |
| AUTH-002 | 单元/API | 邮箱不存在 | 返回用户不存在错误,记录失败日志 |
| AUTH-003 | 单元/API | 密码错误 | 返回密码错误,记录失败日志 |
| AUTH-004 | 单元/API | 锁定用户登录 | 返回账号锁定 |
| AUTH-005 | 单元/API | 普通用户调用管理员登录 | 返回权限不足 |
| AUTH-006 | API | 注册新邮箱 | 用户入库,密码为 BCrypt |
| AUTH-007 | API | 重复邮箱注册 | 返回邮箱已存在 |
| AUTH-008 | API | 刷新 Token | 返回新的 accessToken 和 refreshToken |
| AUTH-009 | API | 非法 refreshToken | 返回 Token 无效 |
| AUTH-010 | API | 登出后使用旧 Token | 被拒绝或命中黑名单 |
| USER-001 | API | 获取当前用户信息 | 返回登录用户资料 |
| USER-002 | API | 管理员分页查询用户 | 返回分页结构 |
| USER-003 | API | 管理员重置密码 | 新密码可登录,旧密码失效 |
| USER-004 | API | 管理员锁定用户 | 被锁定用户无法登录 |
| 组件 | 要求 |
| :--- | :--- |
| JDK | 21 |
| Node.js | **≥ 20**Vite 6 需要现代 Web Crypto;以构建成功为准,建议在 `package.json` 增加 `engines` 并在 CI 锁定) |
| MySQL / Redis | 集成测试推荐使用 Testcontainers;**禁止**让自动化测试默认连接开发机 `application.yml` 中的真实公网地址 |
### 6.2 文章与分类标签
### 3.2 测试 Profile
| 编号 | 类型 | 场景 | 预期 |
| :--- | :--- | :--- | :--- |
| BLOG-001 | 单元/API | 创建草稿 | 状态为草稿,无发布时间 |
| BLOG-002 | 单元/API | 发布文章 | 状态为已发布,生成发布时间 |
| BLOG-003 | 单元/API | 更新文章标签 | 旧关联删除,新关联创建 |
| BLOG-004 | API | 非作者更新文章 | 返回权限不足 |
| BLOG-005 | API | 公开列表仅显示公开已发布 | 草稿、私密、回收站不出现 |
| BLOG-006 | API | 按分类筛选 | 只返回该分类文章 |
| BLOG-007 | API | 按标签筛选 | 只返回该标签文章 |
| BLOG-008 | API | 关键词搜索 | 标题或摘要匹配 |
| BLOG-009 | API | 我的文章列表 | 只返回当前用户文章 |
| BLOG-010 | API | 移入回收站 | 状态变为回收站 |
| BLOG-011 | API | 恢复文章 | 状态变为草稿 |
| BLOG-012 | API | 点赞文章 | 点赞记录创建,计数 +1 |
| BLOG-013 | API | 取消点赞 | 点赞记录删除,计数 -1 且不为负 |
| BLOG-014 | API | 后台文章列表 | 管理员可按状态/分类/关键词筛选 |
| CAT-001 | API | 创建分类 | 分类入库,可在公开列表读取 |
| CAT-002 | API | 重名分类 | 返回唯一性错误 |
| CAT-003 | API | 更新分类 | 名称、描述、排序生效 |
| CAT-004 | API | 删除分类 | 分类不可再查询或被逻辑处理 |
- 使用 `application-test.yml`:数据源与 Redis 来自容器或临时实例;Flyway 开启;JWT 密钥固定测试值。
- 种子用户(示例):
- 管理员:`admin@example.com` 或 Flyway 初始管理员(以 `V2__init_data.sql` 为准);
- 普通用户 A/B:用于交叉评论、点赞;
- 锁定用户:用于登录拒绝场景。
### 6.3 评论
### 3.3 数据命名
| 编号 | 类型 | 场景 | 预期 |
| :--- | :--- | :--- | :--- |
| CMT-001 | 单元/API | 创建根评论 | 评论状态为通过,文章 ID 正确 |
| CMT-002 | 单元/API | 回复根评论 | parentId 正确 |
| CMT-003 | 单元/API | 回复二级评论 | 返回层级限制错误 |
| CMT-004 | API | 非作者删除评论 | 返回权限不足 |
| CMT-005 | API | 作者删除评论 | 评论被删除 |
| CMT-006 | API | 评论列表 | 根评论倒序,回复正序 |
| CMT-007 | API | 点赞评论 | 点赞记录创建,计数 +1 |
| CMT-008 | API | 取消点赞评论 | 点赞记录删除,计数 -1 且不为负 |
| CMT-009 | API | 管理员分页查询评论 | 返回分页结构 |
| CMT-010 | API | 管理员审核评论 | 评论状态更新 |
| CMT-011 | API | 管理员删除评论 | 评论不可见 |
### 6.4 前端页面与交互
| 编号 | 类型 | 场景 | 预期 |
| :--- | :--- | :--- | :--- |
| FE-001 | 单元 | Axios 自动附加 Token | 请求头包含 Bearer Token |
| FE-002 | 单元 | 业务响应 code 非 200 | 展示错误并 reject |
| FE-003 | 单元 | 401 响应 | 清理本地登录态并跳转登录 |
| FE-004 | 单元 | 未登录访问 `/app/dashboard` | 跳转登录并携带 redirect |
| FE-005 | 单元 | 未登录访问 `/admin` | 跳转登录 |
| FE-006 | 组件 | 登录表单提交成功 | 保存 Token 并跳转 |
| FE-007 | 组件 | 注册表单校验失败 | 阻止提交并提示 |
| FE-008 | 组件 | 首页列表加载 | 渲染文章卡片、分页和空状态 |
| FE-009 | 组件 | 文章详情加载 | 渲染正文、点赞、评论 |
| FE-010 | 组件 | 编辑器发布文章 | 调用创建/更新 API |
| FE-011 | 组件 | 后台列表操作 | 筛选、分页、删除/审核确认 |
| FE-012 | 契约 | 前端 API 路径与后端 OpenAPI 对比 | 不允许出现未实现路径 |
### 6.5 安全与异常
| 编号 | 类型 | 场景 | 预期 |
| :--- | :--- | :--- | :--- |
| SEC-001 | API | 无 Token 访问需登录接口 | 返回 401 |
| SEC-002 | API | 普通用户访问 `/api/admin/**` | 返回 403 |
| SEC-003 | API | 管理员访问后台接口 | 成功 |
| SEC-004 | API | 伪造 JWT | 返回 401 |
| SEC-005 | API | 黑名单 JWT | 返回 401 |
| SEC-006 | API | 登录限流 | 超限返回 429 或业务限流错误 |
| SEC-007 | API | 注册限流 | 超限返回 429 或业务限流错误 |
| SEC-008 | API | 文章提交 XSS | 脚本被过滤或拒绝 |
| SEC-009 | API | 评论提交 XSS | 脚本被过滤或拒绝 |
| SEC-010 | 静态扫描 | 配置文件敏感信息 | CI 阻断硬编码密码和密钥 |
- 自动化创建的数据使用前缀 `auto_test_`,用例结束清理或事务回滚。
---
## 7. CI/CD 自动化建议
## 4. 角色与鉴权预期
### 7.1 推荐脚本
| 角色 | JWT RoleSpring `hasRole` | 典型路径 |
| :--- | :--- | :--- |
| 匿名 | 无 | `/api/public/**`、静态资源、`/login``/register` |
| 注册用户 | `ROLE_USER` | `/api/app/**` |
| 管理员 | `ROLE_ADMIN` | `/api/admin/**` |
后端建议新增
**实现提示(来自代码静态阅读)**
```bash
mvn -B clean verify
- `SecurityConfig` 同时包含 `.requestMatchers("/api/article/**", "/api/comment/**", "/api/user/**")`——若路由已统一至 `/api/app/**`,上述行可能为历史遗留;**自动化用例应验证「仅 /api/app/** 与 /api/admin/**」即可覆盖全部业务接口**,并检测是否仍存在未保护「遗留前缀」。
- Token 内角色应与 `ROLE_ADMIN` / `ROLE_USER` 匹配(历史缺陷 BUG-005)。
---
## 5. 已知缺陷与约束(编写用例时必须考虑)
| ID | 描述 | 对测试的影响 |
| :--- | :--- | :--- |
| BUG-010(部分) | `/api/public/captcha` 等为**占位实现**,不做真实图形校验 | 用例应断言「接口存在且返回约定结构」,**不应**按真实验证码安全强度验收 |
| BUG-014 | 限流 Key 维度不足,可能全站共享桶 | 限流用例需记录为**弱保证**;修复后增加 IP/用户维度断言 |
| BUG-015 | 无单测/集成测 | 所有用例当前为**待实现**;本文件提供用例 ID 与步骤模板 |
| 实现差异 | 需求规定访客可查看评论;当前评论列表在 `CommentController` 上位于 `/api/app/comment/**`,通常需要登录 | E2E 若模拟访客读评论:以实际 HTTP 状态为准;建议单独增加 `(实现差异)` 用例记录与需求偏差 |
---
## 6. 测试分层与工具选型(供生成代码时使用)
| 分层 | 工具 | 放置目录 |
| :--- | :--- | :--- |
| 后端单元 | JUnit 5、Mockito、AssertJ | 各模块 `src/test/java` |
| 后端集成 | Spring Boot Test、MockMvc、`@SpringBootTest``@DynamicPropertySource` + TestcontainersMySQL、Redis | 建议集中在 `jog-admin/src/test/java` 或各模块 |
| 契约 | SpringDoc 生成 OpenAPI YAML + 自定义脚本对比 `jog-frontend/src/api` | `scripts/` 或 CI |
| 前端单元/组件 | Vitest、Vue Test Utils、MSW | `jog-frontend` |
| E2E | Playwright | `jog-frontend/e2e/` 或仓库根 `e2e/` |
| 性能冒烟 | k6 或 JMeter | `perf/`(可选) |
---
## 7. 需求验收矩阵 → 自动化用例映射
下列条目**直接服务** `doc/jog-system-requirements.md` 中的 AC。AI 生成用例时:保留 `需求追溯` 列;若实现不满足需求,将 `预期` 改为「记录实际行为 + xfail」。
| 用例 ID | 需求追溯 | 建议分层 | 角色 | 摘要 |
| :--- | :--- | :--- | :--- | :--- |
| R-ADM-LOGIN-01 | AC-ADM-LOGIN-01 | E2E / API | Admin | 正确凭据登录后台,返回 Token |
| R-ADM-LOGIN-02 | AC-ADM-LOGIN-02 | API | Admin | 连续错误触发验证码流程(若已实现) |
| R-ADM-LOGIN-03 | AC-ADM-LOGIN-03 | API | Admin | 连续错误锁定账号 |
| R-USER-REG-01 | AC-USER-REG-01 | API | Anonymous | 合法邮箱注册 |
| R-USER-REG-02 | AC-USER-REG-02 | API | Anonymous | 重复邮箱拒绝 |
| R-USER-REG-03 | AC-USER-REG-03 | FE 单元 / E2E | Anonymous | 弱密码前端拦截 |
| R-USER-REG-04 | AC-USER-REG-04 | API | Anonymous | 同 IP 注册限流 |
| R-USER-LOGIN-01 | AC-USER-LOGIN-01 | E2E / API | User | 用户登录成功 |
| R-USER-LOGIN-02 | AC-USER-LOGIN-02 | API / 集成 | User | 多会话驱逐最早 |
| R-USER-LOGIN-03 | AC-USER-LOGIN-03 | API | User | 错误次数锁定 |
| R-BLOG-PUB-01 | AC-BLOG-PUB-01 | E2E | Anonymous→User | 未登录跳转登录后可回跳编辑器 |
| R-BLOG-PUB-04 | AC-BLOG-PUB-04 | API | User | 私密文章对非作者不可见 |
| R-BLOG-LIST-01 | AC-BLOG-LIST-01 | API | All | 列表排序参数生效 |
| R-BLOG-LIST-05 | AC-BLOG-LIST-05 | API | User / Author | 作者见私密、他人不见 |
| R-BLOG-LIST-06 | AC-BLOG-LIST-06 | API | Author | 作者看自己文章详情浏览量不增 |
| R-COMMENT-01 | AC-COMMENT-01 | E2E | Anonymous | 未登录评论入口拒绝 |
| R-COMMENT-02 | AC-COMMENT-02 | API | User | 四级时折叠为三级平级 |
| R-COMMENT-03 | AC-COMMENT-03 | API | Admin/User | 审核开关与评论状态联动 |
| R-COMMENT-07 | AC-COMMENT-07 | API | User | XSS payload 不执行 |
(其余 AC 按同一模式扩展;性能与安全全局项见第 10、11 节。)
---
## 8. 接口级用例清单(核心回归)
**书写约定**:每条可展开为 Gherkin 或 JUnit `@DisplayName``code` 指业务码,默认成功 `200`(见项目统一约定)。
### 8.1 认证 `/api/public`
| ID | 方法 | 路径 | 角色 | 预期要点 |
| :--- | :--- | :--- | :--- | :--- |
| API-AUTH-001 | POST | `/api/public/user/login` | Anonymous | 成功:`data``accessToken``refreshToken` 或项目实际字段名 |
| API-AUTH-002 | POST | `/api/public/admin/login` | Anonymous | 管理员成功;非管理员拒绝 |
| API-AUTH-003 | POST | `/api/public/user/register` | Anonymous | 成功创建;重复邮箱失败 |
| API-AUTH-004 | POST | `/api/public/refresh-token` | Anonymous | refresh 有效时换新 Token;无效时 401 |
| API-AUTH-005 | GET | `/api/public/captcha` | Anonymous | 200 + 占位数据结构(BUG-010 |
### 8.2 用户 `/api/app/user`、`/api/admin/user`
| ID | 方法 | 路径 | 角色 | 预期要点 |
| :--- | :--- | :--- | :--- | :--- |
| API-USER-001 | GET | `/api/app/user/me` | User | 当前用户资料 |
| API-USER-002 | POST | `/api/app/user/{id}/follow` | User | 关注成功 |
| API-USER-003 | DELETE | `/api/app/user/{id}/follow` | User | 取关成功 |
| API-USER-004 | POST | `/api/app/user/logout` | User | 会话或黑名单生效(按实现) |
| API-USER-010 | GET | `/api/admin/user/list` | Admin | 分页 `PageResult` |
| API-USER-011 | PUT | `/api/admin/user/{id}/reset-password` | Admin | 重置后可登录 |
| API-USER-012 | PUT | `/api/admin/user/{id}/status` | Admin | 锁定后登录失败 |
### 8.3 文章(公开)`/api/public/article`
| ID | 方法 | 路径 | 角色 | 预期要点 |
| :--- | :--- | :--- | :--- | :--- |
| API-PUB-ART-001 | GET | `/api/public/article/list` | Anonymous | 仅公开已发布;分页字段齐全 |
| API-PUB-ART-002 | GET | `/api/public/article/{id}` | Anonymous | 详情;标签为结构化 `Tag`BUG-013 修复预期) |
### 8.4 文章(用户)`/api/app/article`
| ID | 方法 | 路径 | 角色 | 预期要点 |
| :--- | :--- | :--- | :--- | :--- |
| API-APP-ART-001 | POST | `/api/app/article` | User | 创建成功返回 id |
| API-APP-ART-002 | PUT | `/api/app/article/{id}` | User | 作者可改;非作者 403 |
| API-APP-ART-003 | GET | `/api/app/article/mine` | User | 仅本人文章 |
| API-APP-ART-004 | PUT | `/api/app/article/{id}/recycle` | User | 回收站状态 |
| API-APP-ART-005 | PUT | `/api/app/article/{id}/restore` | User | 恢复 |
| API-APP-ART-006 | DELETE | `/api/app/article/{id}` | User | 删除 |
| API-APP-ART-007 | POST | `/api/app/article/{id}/like` | User | 点赞切换 |
### 8.5 文章(管理)`/api/admin/article`
| ID | 方法 | 路径 | 角色 | 预期要点 |
| :--- | :--- | :--- | :--- | :--- |
| API-ADM-ART-001 | GET | `/api/admin/article/list` | Admin | 后台列表 |
| API-ADM-ART-002 | DELETE | `/api/admin/article/{id}` | Admin | 管理员删除 |
### 8.6 分类 `/api/public/category`、`/api/admin/category`
| ID | 方法 | 路径 | 角色 | 预期要点 |
| :--- | :--- | :--- | :--- | :--- |
| API-CAT-001 | GET | `/api/public/category/list` | Anonymous | 列表 |
| API-CAT-010 | POST | `/api/admin/category` | Admin | 创建 |
| API-CAT-011 | PUT | `/api/admin/category/{id}` | Admin | 更新 |
| API-CAT-012 | DELETE | `/api/admin/category/{id}` | Admin | 删除 |
### 8.7 标签 `/api/public/tag`、`/api/admin/tag`
| ID | 方法 | 路径 | 角色 | 预期要点 |
| :--- | :--- | :--- | :--- | :--- |
| API-TAG-001 | GET | `/api/public/tag/list` | Anonymous | 列表 |
| API-TAG-010 | POST | `/api/admin/tag` | Admin | `name` 参数创建 |
### 8.8 评论 `/api/app/comment`、`/api/admin/comment`
| ID | 方法 | 路径 | 角色 | 预期要点 |
| :--- | :--- | :--- | :--- | :--- |
| API-CMT-001 | POST | `/api/app/comment` | User | 创建评论 |
| API-CMT-002 | DELETE | `/api/app/comment/{id}` | User | 删除本人评论 |
| API-CMT-003 | GET | `/api/app/comment/article/{articleId}` | User | 树形列表(**若需访客可读应另有公开接口—当前可能需登录**) |
| API-CMT-004 | POST | `/api/app/comment/{id}/like` | User | 点赞切换 |
| API-CMT-010 | GET | `/api/admin/comment/list` | Admin | 分页列表 |
| API-CMT-011 | PUT | `/api/admin/comment/{id}/audit` | Admin | 审核 |
| API-CMT-012 | DELETE | `/api/admin/comment/{id}` | Admin | 删除 |
---
## 9. 安全与负向用例(必测)
| ID | 场景 | 预期 |
| :--- | :--- | :--- |
| SEC-001 | 无 Token 调 `/api/app/article` POST | 401 |
| SEC-002 | User Token 调 `/api/admin/user/list` | 403 |
| SEC-003 | Admin Token 调 `/api/admin/**` | 200(合法操作下) |
| SEC-004 | 篡改签名的 JWT | 401 |
| SEC-005 | 已登出/黑名单 JWT | 401(若实现黑名单) |
| SEC-006 | 登录接口暴力请求 | 429 或业务限流码 |
| SEC-007 | 文章/评论 body 携带 `<script>` | 存储或展示侧无害化 |
---
## 10. 非功能与性能(源自于需求文档)
| ID | 类型 | 条件 | 工具建议 |
| :--- | :--- | :--- | :--- |
| NF-PERF-01 | 接口延迟 | 列表/详情 P95 ≤ 需求文档值 | k6 |
| NF-PERF-02 | 前端首屏 | Lighthouse 4G ≤ 2s | Lighthouse CI |
| NF-SEC-01 | 密码存储 | DB 中为 BCrypt | JDBC 断言 |
| NF-AVAIL-01 | 并发 | 500 并发错误率 < 1% | k6 |
---
## 11. 前端专项(Vitest / Playwright
| ID | 范围 | 场景 |
| :--- | :--- | :--- |
| FE-001 | `utils/request` | 请求携带 `Authorization` |
| FE-002 | `utils/request` | `code !== 200` 时 reject |
| FE-003 | `utils/request` | 401 清 token 并跳转登录 |
| FE-004 | `router` | `requiresAuth` 拦截 |
| FE-005 | `router` | `requiresAdmin` 非管理员重定向(BUG-011 相关) |
| FE-E2E-01 | Playwright | 访客首页→详情 |
| FE-E2E-02 | Playwright | 用户登录→发文→可见 |
| FE-E2E-03 | Playwright | 管理员审核评论 |
---
## 12. Flyway 与持久化
| ID | 场景 | 预期 |
| :--- | :--- | :--- |
| DB-001 | 空库启动 | `V1`/`V2` 应用成功,`flyway_schema_history` 成功 |
| DB-002 | 重复启动 | 迁移不失败 |
| DB-003 | 实体 CRUD | 插入后按 `sys_*` / `blog_*` 表可读 |
---
## 13. AI 生成用例时的输出模板(强制)
每条用例应包含以下字段(JSON 或表格均可):
```text
id: <本节已定义 ID>
title: <短标题>
layer: <unit|integration|contract|e2e>
role: <anonymous|user|admin>
preconditions: <数据与配置>
steps:
1. ...
2. ...
expected:
http: <状态码>
body: <关键 JSON 路径与值>
side_effects: <数据库/Redis 可选>
trace: <R-* / API-* / SEC-* / BUG-*>
flaky_notes: <可选>
```
前端建议新增:
```bash
npm ci
npm run test:unit
npm run test:component
npm run build
npm run test:e2e
```
### 7.2 推荐新增依赖与脚本
后端:
- 在父 POM 统一管理测试依赖:JUnit 5、Mockito、AssertJ、Testcontainers MySQL/Redis、Spring Security Test、JaCoCo。
- 将测试依赖下沉到需要测试的模块,避免只有启动模块能写测试。
- 配置 Maven Surefire/Failsafe,区分单元测试和集成测试。
前端:
- 新增 Vitest、Vue Test Utils、jsdom、MSW、Playwright。
-`package.json` 中新增:
- `test:unit`
- `test:component`
- `test:e2e`
- `test:e2e:ui`
- `coverage`
### 7.3 Pipeline 阶段
1. 依赖安装与缓存。
2. 后端编译与单元测试。
3. 后端集成测试,启动 MySQL/Redis Testcontainers。
4. 生成 OpenAPI 文档。
5. 前端 API 封装与 OpenAPI 契约对比。
6. 前端单元/组件测试。
7. 前端生产构建。
8. 启动完整应用,运行 Playwright E2E 冒烟。
9. 上传测试报告、覆盖率报告和 E2E 截图/视频。
---
## 8. 缺陷分级与处理策略
## 附录 A:当前后端路由一览(扫描自代码,2026-05-18)
| 等级 | 定义 | 示例 | 处理要求 |
| :--- | :--- | :--- | :--- |
| P0 | 系统不可用或核心数据损坏 | 无法启动、登录全失败、发文数据丢失 | 立即阻断发布 |
| P1 | 核心业务不可用或严重安全问题 | 普通用户可访问后台、Token 绕过、评论 XSS | 阻断合并/发布 |
| P2 | 重要功能异常但有规避方式 | 筛选错误、分页异常、后台单项操作失败 | 发布前修复或明确延期 |
| P3 | 轻微体验或边界问题 | 文案不准、空状态异常、非核心兼容问题 | 排入迭代 |
---
## 9. 当前优先落地路线
### 第一阶段:补齐基础测试设施
- 后端新增 `src/test` 目录、`application-test.yml`、JUnit/Mockito/Testcontainers/JaCoCo。
- 前端新增 Vitest、Vue Test Utils、MSW、Playwright。
- 建立 CI 基础命令:后端 `mvn verify`,前端 `npm run build` + 单元测试。
### 第二阶段:先保护最容易出事故的链路
- 认证:登录、注册、刷新、登出、管理员权限。
- 契约:前端 API 路径和后端 Controller/OpenAPI 对比。
- 文章:创建、发布、列表、详情、更新、删除、点赞。
- 评论:创建、列表、回复、删除、审核、点赞。
### 第三阶段:增强安全与发布信心
- XSS、限流、JWT 黑名单、CORS、敏感信息扫描。
- Flyway 迁移全量验证。
- Playwright 覆盖访客、普通用户、管理员三类角色端到端流程。
- k6/JMeter 做核心接口性能冒烟。
---
## 10. 风险清单
| 风险 | 影响 | 建议 |
| Controller 类 | 前缀 | 方法摘要 |
| :--- | :--- | :--- |
| 前后端 API 路径不一致 | 前端页面调用失败 | 优先建立契约测试,并统一 `/api/auth``/api/article``/api/comment``/api/app/**` 路由规范 |
| 生产/公网中间件配置在默认配置中 | 自动化测试可能误连真实服务 | 建立 `application-test.yml`CI 强制覆盖数据源 |
| 自有测试目录缺失 | 回归依赖人工验证 | 先补 Service 单元测试和 Controller 集成测试 |
| 需求文档与代码实现差异 | 验收标准不清 | 将未实现需求标为 pending/xfail,并建立需求追踪 |
| 前端缺少测试脚本 | UI 回归成本高 | 引入 Vitest 和 Playwright,先覆盖核心旅程 |
| 点赞计数并发更新 | 可能出现计数错乱或负数 | 加并发集成测试,必要时改为原子 SQL 更新 |
| 评论和文章富文本安全 | XSS 风险 | 加 payload 回归测试,确认过滤链路覆盖请求体 |
| `AuthController` | `/api/public` | `POST /user/login``POST /admin/login``POST /user/register``GET /captcha``POST /refresh-token` |
| `UserController`(用户) | `/api/app/user` | `GET /me``GET /{id}``POST/DELETE /{id}/follow``POST /logout` |
| `UserController`(管理) | `/api/admin/user` | `GET /list``PUT /{id}/reset-password``PUT /{id}/status` |
| `PublicArticleController` | `/api/public/article` | `GET /list``GET /{id}` |
| `ArticleController` | `/api/app/article` | `POST /``PUT /{id}``GET /mine``PUT /{id}/recycle``PUT /{id}/restore``DELETE /{id}``POST /{id}/like` |
| `AdminArticleController` | `/api/admin/article` | `GET /list``DELETE /{id}` |
| `PublicCategoryController` | `/api/public/category` | `GET /list` |
| `AdminCategoryController` | `/api/admin/category` | `POST /``PUT /{id}``DELETE /{id}` |
| `PublicTagController` | `/api/public/tag` | `GET /list` |
| `AdminTagController` | `/api/admin/tag` | `POST /``name` 请求参数) |
| `CommentController` | `/api/app/comment` | `POST /``DELETE /{id}``GET /article/{articleId}``POST /{id}/like` |
| `AdminCommentController` | `/api/admin/comment` | `GET /list``PUT /{id}/audit``DELETE /{id}` |
**前端契约检查**:须将上述列表与 `jog-frontend/src/api/**/*.js` 中的 `url``method` 逐一比对。
---
## 11. 验收标准
## 附录 B:与历史文档的关系
自动化测试计划落地后,应满足:
| 文档 | 角色 |
| :--- | :--- |
| `jog-system-requirements.md` | 业务验收与 AC 编号来源 |
| `jog-system-technical-design.md` | 架构与表结构参考;**路径以附录 A 为准** |
| `jog-system-deployment-checklist.md` | 上线人工/半自动巡检清单,可择优改为 E2E |
| `jog-system-bug-list.md` | 历史测试执行与缺陷台账;编写回归时注意已关闭项 |
- 每次合并请求自动运行后端单元测试、集成测试、前端单元/组件测试和构建。
- 每次发布前自动运行核心 E2E、数据库迁移验证和安全回归。
- 测试报告可追溯到用例、模块、提交和失败截图/日志。
- 新增核心业务功能必须同步新增或更新自动化用例。
- P0/P1 自动化失败不得合并,不得发布。
---
> **文档结束**
> 本文档 V2.0 合并了 `doc` 目录全部文件中与测试相关的信息,并校准当前仓库实现;作为 AI 编写测试用例时的**唯一输入**时,请优先遵循第 13 节用例模板及附录 A 路径,缺失的自动化实现以第 1.2 节「未执行项」为 backlog。