E2E 测试是什么?学 Harness 工程时第一次搞懂它

📅 2026/7/8 3:03:13
E2E 测试是什么?学 Harness 工程时第一次搞懂它
E2E 测试是什么学 Harness 工程时第一次搞懂它DONE.md 里有一行不起眼的 checkbox「E2E smoke 测试通过」。我盯着它看了半天不知道 E2E 是什么更不知道它为什么跟编译、单元测试并列为「完成标准」。这篇文章把当时搞明白的东西从头讲一遍。目录DONE.md 里的一行代码E2E 到底是什么为什么单元测试不够E2E 测试家族Smoke / Sanity / 全面 E2EE2E 在 Harness 工程中的位置常用工具速览第一个 E2E 测试长什么样写在最后DONE.md 里的一行代码前阵子在学 Harness 工程读到项目的完成标准文件DONE.md。这个文件的作用很简单列一个 checklist所有条目都打勾了任务才算完成。功能完成标准大概长这样- [ ] 编译通过mvn clean package -DskipTests 无报错 - [ ] 单元测试通过mvn test -pl ruoyi-business - [ ] 新增功能有对应测试TDD先写测试再写实现 - [ ] 前端构建通过npm run build:prod - [ ] E2E smoke 测试通过npm run test:smoke - [ ] 涉及数据库变更的SQL 增量脚本已更新到 sql/前几条我都认识编译、单元测试、前端构建都是日常在做的。但第五条「E2E smoke 测试通过」我第一次见。E2E 是什么Smoke 又是什么为什么它跟编译、单元测试并列是完成标准的硬性要求查了一圈资料之后搞明白了。这篇文章把 E2E 测试从零讲一遍面向跟我当时一样「听过但说不清楚」的开发者。E2E 到底是什么E2E 是 End-to-End 的缩写中文叫「端到端测试」。一句话解释站在真实用户的角度模拟操作流程验证整个系统从头到尾能不能跑通。「端到端」的两个「端」分别是前端用户看到的界面、点击的按钮、输入的表单后端服务器处理请求、查数据库、返回结果中间经过的所有环节——前端渲染、API 调用、后端逻辑、数据库读写——E2E 测试全部走一遍。拿一个具体的业务场景举例。用户在运维管理平台上提交一条问题记录用户打开问题列表页 → 点击「新增问题」按钮 → 填写问题描述、选择试验点 → 提交表单 → 前端发 POST 请求到后端 API → 后端 Service 处理业务逻辑写入数据库 → 返回成功响应 → 前端刷新列表新记录出现E2E 测试就是用代码模拟上面这整条链路。它不管你后端用了什么框架、前端用了什么组件库它只关心一件事用户操作之后预期的结果有没有出现。用 ASCII 画一下数据流┌──────────┐ HTTP ┌──────────┐ SQL ┌──────────┐ │ 用户操作 │ ─────────▶ │ 后端 API │ ─────────▶ │ 数据库 │ │ (前端) │ ◀───────── │ (Service) │ ◀───────── │ (MySQL) │ └──────────┘ 响应结果 └──────────┘ 查询结果 └──────────┘ E2E 测试验证这条完整链路能不能跑通结果对不对这跟单元测试不一样。单元测试只测一个零件——比如 Service 层的某个方法输入 A 是不是返回 B。E2E 测试测的是整辆车——从用户踩油门到车子跑起来中间每个环节都得对。为什么单元测试不够你可能会问项目已经有单元测试了为什么还要 E2E单元测试验证的是零件质量E2E 验证的是整车能不能开。零件都合格不代表装在一起能跑。说一个我遇到过的真实场景。一个后端模块Service 层的单元测试全绿——每个方法单独测都对。但前端调接口的时候返回格式跟前端期望的不一致。单元测试没发现这个问题因为它测的是 Service 内部逻辑不涉及 API 返回格式。E2E 测试能发现因为它走的是完整的「前端请求 → 后端处理 → 返回结果」链路。在 AI Coding 的场景下这个问题更突出。AI 写代码的特点是每个零件可能都对但组装起来容易出问题。比如 AI 给后端加了一个接口字段名用驼峰前端调的时候用了下划线。两边的单元测试各自通过合在一起就报错。E2E 测试从用户视角走一遍这种跨层的问题一眼就能看出来。单元测试告诉你「这个方法对不对」E2E 测试告诉你「这个功能能不能用」。E2E 测试家族Smoke / Sanity / 全面 E2EE2E 不是一个单一概念它下面分了好几种。你看到的 DONE.md 里写的是「E2Esmoke测试」不是「E2E 测试」。这个 smoke 前缀有讲究。测试类型测什么目的什么时候跑E2E Smoke 测试系统关键端到端流程如登录→下单→支付快速验证核心功能是否可用每次代码提交、部署后或生产环境定时监控全面 E2E 测试系统大部分或全部业务流程全面验证各业务流程的功能正确性测试阶段或发版前耗时较长10-30 分钟冒烟测试 (Smoke Test)最基本、最核心的功能点确保被测版本「可测」不会让后续测试阻塞新版本提交后正式测试开始前健全测试 (Sanity Test)被修改或新增的特定功能模块快速验证修复或新功能是否破坏了原有功能收到修复补丁或新功能后这四个容易搞混核心区别在范围和时机Smoke范围最小跑最快回答「系统活着吗」Sanity范围稍大回答「这次改动有没有搞坏别的」全面 E2E范围最大回答「所有功能都正常吗」为什么 DONE.md 里用的是 Smoke 而不是全面 E2E因为 Smoke 是部署门禁——每次代码提交或部署后立刻跑几分钟内出结果。如果 Smoke 都过不了后面的全面测试不用跑了直接打回。Smoke 测试的两个核心场景场景一部署门禁。代码部署到测试环境或生产环境后立刻跑 Smoke。通过了才允许继续失败了直接阻断避免浪费后续的测试资源。场景二生产监控。在生产环境每 5-15 分钟定时跑 Smoke。相当于 7x24 小时的自动巡检核心功能一出问题立刻告警。Smoke 测试测试环境CI/CD开发者Smoke 测试测试环境CI/CD开发者alt[测试通过][测试失败]代码提交自动部署触发 Smoke 测试✅ 核心功能正常继续后续流程❌ 阻断核心功能异常停止发布Smoke 测试的价值在于用最小的成本最快地拿到核心功能是否正常的反馈。不追求覆盖面追求速度和确定性。E2E 在 Harness 工程中的位置回到最开始的 DONE.md。再看一遍那几条功能完成标准1. 编译通过 ← 代码能编译 2. 单元测试通过 ← 零件没问题 3. 新增功能有对应测试 ← TDD 保障 4. 前端构建通过 ← 前端能打包 5. E2E smoke 测试通过 ← 整车能跑这五条不是随便列的它们有顺序从零件到整车从局部到整体。E2E Smoke 是最后一道闸门——前四条全过了E2E 再验证一次完整的业务流程全过了才算完成。在 Harness 工程的 9 步开发流程中E2E 测试出现在第 6 步「集成验证」编译 单测 E2E Smoke第0步 准备第1步 探索第2步 提案第3步 审核第4步 拆任务第5步 TDD实现第6步 集成验证第7步 代码审查第8步 归档第 5 步 TDD 实现写完代码后第 6 步跑集成验证——编译、单元测试、E2E Smoke 一起上。全部通过才能进入第 7 步的代码审查。这个设计的逻辑很清晰AI 写的代码零件级验证单元测试和整车级验证E2E缺一不可。单元测试保证每个方法对E2E 保证整个功能能用。Harness 把这两层验证都写进了完成标准不给 AI「只写单元测试就交差」的机会。E2E Smoke 不是可选项是完成标准的硬性要求。没跑过 E2E任务就不能算完成。常用工具速览写 E2E 测试需要自动化工具。主流的有三个工具一句话定位适合场景Playwright微软出品API 现代多浏览器支持可靠性高新项目首选适合大部分 Web 项目Cypress对前端框架友好调试体验好React / Vue 项目前端团队主导Selenium老牌工具生态成熟支持语言多遗留项目、需要跨语言集成新手推荐从 Playwright 开始。理由很简单API 设计现代async/await 风格自动等待机制减少了 flaky tests时好时坏的测试支持 Chromium / Firefox / WebKit 三种浏览器社区活跃文档齐全。如果你的项目是 Vue 3 Spring Boot跟我学 Harness 时的项目一样Playwright 是最省心的选择。它不关心你前端用什么框架只管打开浏览器、模拟操作、检查结果。第一个 E2E 测试长什么样用一个伪代码例子展示 E2E 测试的核心结构。假设我们要测用户登录流程test(用户登录成功后能看到首页,async({page}){// 第一步打开登录页awaitpage.goto(http://localhost:3000/login);// 第二步填写表单awaitpage.fill(#username,admin);awaitpage.fill(#password,123456);// 第三步点击登录按钮awaitpage.click(#login-btn);// 第四步断言结果awaitexpect(page).toHaveURL(/dashboard);awaitexpect(page.locator(.welcome-msg)).toContainText(欢迎);});四个步骤对应 E2E 测试的核心要素步骤作用对应操作打开页面进入测试起点page.goto()模拟操作填表单、点按钮page.fill()/page.click()等待响应系统处理请求Playwright 自动处理断言结果验证预期是否达成expect()注意看这段测试代码——它写的是用户行为不是代码实现。它不知道后端用了 Spring Boot 还是 Express不知道数据库是 MySQL 还是 PostgreSQL不知道登录逻辑用了 JWT 还是 Session。它只知道输入用户名密码、点登录、应该跳转到首页。这就是 E2E 测试的特点从用户视角出发验证的是业务结果不关心技术实现。如果哪天后端换了框架只要用户操作流程和结果不变E2E 测试不需要改。写在最后回到最开始那个问题DONE.md 里的「E2E smoke 测试通过」到底是什么意思现在清楚了它是端到端冒烟测试站在用户角度走一遍核心业务流程验证系统整体能不能正常工作。它不追求覆盖面追求的是速度——几分钟内告诉你核心功能是否「活着」。在 Harness 工程的完成标准里E2E Smoke 是最后一道闸门。编译通过、单元测试通过、前端构建通过之后E2E Smoke 再验证一次完整的业务链路。全过了任务才算完成。如果你也在用 AI Coding 做业务项目建议把 E2E Smoke 加到你的完成标准里。不需要一开始就写很多先覆盖最核心的一两条流程就行。比如用户登录、创建一条记录、查看详情——这三个场景跑通了系统基本不会出大问题。工具选 Playwright上手快文档好跑起来省心。E2E 测试的价值就一句话用最小的成本最快地告诉你系统核心功能是否正常。