# Jog System 自动化测试规范(AI 测试用例唯一输入) > **更新**:需求级**全量展开**且文件名含 Cursor 的单一输入见 [`jog-system-cursor-automated-test-spec.md`](jog-system-cursor-automated-test-spec.md)。本文档保留为精简版路由与执行现状摘要。 | 属性 | 内容 | | :--- | :--- | | 文档版本 | V2.0 | | 生成日期 | 2026-05-18 | | 用途 | **仅依赖本文档**即可推导可执行的自动化测试用例(单元 / 集成 / 契约 / 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. 当前已执行的测试与验证(事实记录) 以下内容来自对仓库的一次质量核验(详见 `doc/jog-system-bug-list.md`),代表**截至文档日期的真实执行状況**,而非目标态。 ### 1.1 已执行项 | 序号 | 类别 | 命令或方式 | 结果摘要 | | :---: | :--- | :--- | :--- | | 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 明确未执行 / 缺失项 | 序号 | 说明 | | :--- | :--- | | N-01 | **无任何** `src/test/java` 下的单元测试或集成测试(仓库扫描为 0 个测试类) | | N-02 | **无** Vitest / Playwright / Cypress 等前端或 E2E 套件 | | N-03 | **无** CI 中可重复的契约 diff(OpenAPI vs `src/api`)流水线步骤 | --- ## 2. 测试目标与质量门禁(目标态) ### 2.1 目标 - 核心链路:认证、注册、Token 刷新、文章 CRUD 与列表、评论、分类/标签、后台用户管理与审核。 - 横切能力:JWT 鉴权、角色(`ROLE_ADMIN` / `ROLE_USER`)、统一响应 `ApiResult`、分页 `PageResult`、限流、`XssFilter`、Flyway 迁移可重复执行。 - **前后端契约**:HTTP 方法、路径、请求/响应 JSON 字段与前端封装一致。 - **需求对齐**:凡本文档标记为 `(需求)` 的用例,应以 `doc/jog-system-requirements.md` 中同名 AC 为判定依据;标记为 `(实现差异)` 的,以当前代码为准并建议产品确认。 ### 2.2 建议门禁(落地后) | 阶段 | 必跑项 | | :--- | :--- | | 本地/PR | `mvn -B verify`(含单测+集成)、前端 `npm run build`、`npm run test:unit`、OpenAPI↔前端 API 契约检查 | | 发布前 | Testcontainers 集成测试全绿、核心 Playwright 冒烟、Flyway 干净库迁移 | | 上线后 | 部署清单 `doc/jog-system-deployment-checklist.md` 第 11 节选段自动化或半自动巡检 | ### 2.3 覆盖率期望(指导 AI 分优先级) - 后端:Service 核心分支优先;Controller/MockMvc 覆盖所有附录 A 中带「写操作」或「鉴权敏感」的接口。 - 前端:`utils/request.js`(Token、401/403/429)、`router`(`requiresAuth` / `requiresAdmin`)、各业务 `src/api/*.js`。 - E2E:访客可读、用户发文与评论、管理员审核与删文的最短路径。 --- ## 3. 测试环境与数据约定 ### 3.1 运行时版本 | 组件 | 要求 | | :--- | :--- | | JDK | 21 | | Node.js | **≥ 20**(Vite 6 需要现代 Web Crypto;以构建成功为准,建议在 `package.json` 增加 `engines` 并在 CI 锁定) | | MySQL / Redis | 集成测试推荐使用 Testcontainers;**禁止**让自动化测试默认连接开发机 `application.yml` 中的真实公网地址 | ### 3.2 测试 Profile - 使用 `application-test.yml`:数据源与 Redis 来自容器或临时实例;Flyway 开启;JWT 密钥固定测试值。 - 种子用户(示例): - 管理员:`admin@example.com` 或 Flyway 初始管理员(以 `V2__init_data.sql` 为准); - 普通用户 A/B:用于交叉评论、点赞; - 锁定用户:用于登录拒绝场景。 ### 3.3 数据命名 - 自动化创建的数据使用前缀 `auto_test_`,用例结束清理或事务回滚。 --- ## 4. 角色与鉴权预期 | 角色 | JWT Role(Spring `hasRole`) | 典型路径 | | :--- | :--- | :--- | | 匿名 | 无 | `/api/public/**`、静态资源、`/login`、`/register` | | 注册用户 | `ROLE_USER` | `/api/app/**` | | 管理员 | `ROLE_ADMIN` | `/api/admin/**` | **实现提示(来自代码静态阅读)**: - `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` + Testcontainers(MySQL、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 携带 `