AUTOMATION TEST · UI/接口 / CI 集成

自动化测试速查

从分层投入与工具选型,到 Web UI 定位与等待策略、接口用例分层与断言设计,再到 App 自动化、CI 流水线集成与 flaky 用例治理,自动化测试方向的 44 条高频要点一张表收齐,随查随用。

44条速查 8大主题 持续更新

📖 速查表

点击展开各小节

🧭 分层与选型
层级 / 工具说明选型要点
投入比 · 测试金字塔 单元 > 接口 > UI 的金字塔投入结构:越往下越快、越稳、越便宜,接口层是性价比最高的一层 UI 只覆盖核心链路 重心下移
Selenium 老牌 Web UI 标准:浏览器兼容面广、生态与资料最全;需自管驱动,无原生自动等待 存量项目与老旧浏览器兼容场景 生态最全
Playwright 新一代 Web UI 框架:自动等待、多浏览器一套 API、原生录制与 trace 调试 新项目首选 现代能力全
Cypress 运行在浏览器内部,执行与调试体验好;但同源限制、多标签页 / 多域支持弱 前端团队内自测友好 局限也明显
Requests / RestAssured Python / Java 生态的接口自动化事实标准,配合断言库构建接口回归集 接口层主力
Appium 移动端自动化统一协议层:一套 WebDriver API 驱动 Android 与 iOS 跨平台移动测试首选
pytest / JUnit 测试框架基座:pytest 以 fixture 机制与插件生态见长,JUnit 5 是 Java 生态标配 先定框架再写用例
🎭 Web UI 自动化
UI 自动化最贵的两件事是定位与等待:定位抗重构、等待不硬等,用例就稳了大半。
主题说明要点
Playwright vs Selenium 核心差异:自动等待 vs 手写等待;原生 trace / 录制 / 网络拦截 vs 依赖第三方插件;并行与浏览器管理更现代 新项目选 Playwright 省一半维护量 对比要点
定位策略 · 语义优先 get_by_role / get_by_label / get_by_text 按用户可感知语义定位,最贴近真实使用且最抗重构 推荐顺序第一位
定位策略 · CSS / XPath CSS 选择器性能好、够用;XPath 能按层级与文本找元素但更脆弱,绝对路径一律禁用 data-testid 专用属性最稳 语义兜底
显式等待 按条件等待:元素可见、可点击、文本出现才继续;是三类等待中唯一推荐的生产用法 WebDriverWait + expected_conditions 首选
隐式等待 全局设置元素查找的轮询超时;与显式等待混用会导致等待时间叠加且行为难预测 避免混用
强制等待 固定 sleep 死等:网络快了浪费时间、网络慢了照样挂,是 flaky 用例的头号来源 仅限临时调试 用例中禁用
POM 页面对象模式 每个页面封装一个类:元素定位与页面操作收在页对象里,用例只写业务流程 页面变了只改一处 结构与用例分离
🔌 接口自动化
主题说明要点
用例分层 · 单接口 参数校验、异常码、鉴权、边界值:执行快、定位准,是接口回归集的量与底盘 量大管饱
用例分层 · 场景链 多接口串成业务流(下单 → 支付 → 退款),上下游字段取值传递,验证状态机流转 关注接口间依赖与数据传递 业务闭环
用例分层 · 资损类 金额计算、重复支付、幂等、并发扣减:必测且单独打标,失败按最高优先级处理 单独标记必测
断言 · 状态码与结构 第一层断言 HTTP 状态码语义正确,第二层断言 JSON 结构与关键字段存在、类型正确 先结构后取值,失败信息更可读
断言 · 业务字段与 DB 关键业务字段精确断言;金额、状态等落库值与接口返回、DB 记录三方交叉校验 落库校验防假成功
数据驱动 · CSV / YAML 一份用例逻辑配多份数据文件,pytest 用 parametrize 或外部文件驱动,新增场景只加数据 逻辑与数据分离
数据驱动 · 工厂方法 造数工厂生成带「有效默认值」的请求对象,用例只覆盖与场景相关的差异字段 新增字段不破坏全量用例 屏蔽无关字段
📱 App 自动化
主题说明要点
Appium 架构一句话 WebDriver 协议统一测试指令,Appium Server 把指令翻译给各平台驱动(Android 的 UiAutomator2 / iOS 的 XCUITest)在真机或模拟器上执行 一套 API 双平台
Android 差异要点 adb 管理设备、UiAutomator2 驱动执行、uiautomatorviewer / Appium Inspector 定位元素、权限可在安装时自动授予 设备碎片化需多分辨率覆盖 生态开放
iOS 差异要点 依赖 macOS + Xcode + XCUITest 驱动,应用必须开发者签名;元素定位体系与 Android 不同 环境搭建成本高 签名是前置条件
稳定性 · 等待策略 以元素可见 / 可点击的条件等待为主,兼顾页面加载与动画时长;避免固定 sleep 条件等待优先
稳定性 · 权限弹窗 启动时统一处理系统权限弹窗:Android 配 autoGrantPermissions,iOS 预置弹窗自动点击,避免用例被随机弹窗打断 弹窗前置治理
🤖 CI 集成
自动化测试不进流水线就只是脚本:触发分层、门禁卡点、报告可查,才算资产。
主题说明要点
触发 · 提交触发 每次 push / PR 跑核心冒烟集,控制在 10~15 分钟内,快速反馈挡住低级回归 分钟级反馈
触发 · 定时回归 夜间跑全量回归集,白天上班先看报告、把失败用例分派到责任人 快慢分离
触发 · 发布门禁 核心链路用例 100% 通过才允许发布;豁免必须写明理由与风险,留痕可查 门禁不容讨价还价
Allure 一句话 测试报告框架:按 feature / story 组织用例,附步骤、截图、日志附件,失败原因一眼可查 报告即看板
失败重试策略 仅对网络 / 环境类失败做有限重试(如 2 次),且每次重试必须记录进报告;重试率升高说明有系统性问题 重试掩盖症状不治根因
告警分级 核心链路失败 → 即时群通知 @ 责任人;非核心失败 → 每日汇总邮件,避免告警疲劳 分级通知降噪
🧯 稳定性治理
主题说明要点
成因一 · 等待滥用 固定 sleep 太短环境一慢就挂、太长拖慢整体;环境抖动被放大成用例失败 改条件等待 flaky 头号来源
成因二 · 环境依赖 共享环境被他人改配置、第三方接口抖动、测试设备被占用,用例随环境起舞 关键依赖 mock 或独立测试环境
成因三 · 数据污染 用例间共享数据互相干扰、历史脏数据累积,换个执行顺序就失败 数据自造自清理 三大成因
隔离 · 独立账号与数据 并发执行的用例使用独立账号与独立数据集,从物理上消除相互影响 物理隔离
隔离 · 用后清理 fixture / teardown 保证「谁创建谁销毁」;清理失败也要留痕,宁可多跑一条清理用例 用完即净
维护节奏与责任人 flaky 用例先移出回归集、挂看板限期修复;每条用例明确责任人,需求变更时同步维护用例 无主用例必腐化
🎬 Playwright 起步脚本

一条能直接跑通的最小用例:运行器自动 launch 浏览器 → goto 打开页面 → getByRole 语义定位点击 → expect 自动重试断言 → trace 回放与截图留证据。

import { test, expect } from '@playwright/test'; test('登录成功进入工作台', async ({ page }) => { // 0. 运行器已自动 launch 浏览器;脱离 runner 时可手动:await chromium.launch() // 先开启 trace:失败时可在报告里逐步回放操作,定位不靠猜 await page.context().tracing.start({ snapshots: true, screenshots: true }); // 1. 打开登录页 await page.goto('https://app.example.com/login'); // 2. 语义定位:按可访问角色 + 名称找元素,比 class / id 更抗前端重构 await page.getByRole('textbox', { name: '用户名' }).fill('qa-user'); await page.getByLabel('密码').fill('pass-123'); // 3. 点击登录按钮 await page.getByRole('button', { name: '登录' }).click(); // 4. expect 断言自带自动重试:默认 5s 内轮询等待,绝不手写 sleep await expect(page).toHaveURL(/.*dashboard/); await expect(page.getByRole('heading', { name: '工作台' })).toBeVisible(); // 5. 收尾留证据:trace 落盘可在报告中回放,整页截图随报告归档 await page.context().tracing.stop({ path: 'trace.zip' }); await page.screenshot({ path: 'dashboard.png', fullPage: true }); });
🎯 元素定位避坑
避坑点反例 → 正解一句话要点
不用绝对 XPath /html/body/div[2]/div[1]/table[3]/... 前端一调布局全部失效 → 换语义定位或稳定属性 绝对路径禁止进代码库 最脆弱定位
优先语义定位 getByRole / getByLabel / getByText 按用户视角找元素;语义缺失本身就是可访问性缺陷,顺手推动前端补齐 页面越好用例越稳 抗重构首选
动态 id 用 data-testid 构建生成的 id(如 field-8f3a2)每次都变 → 与前端约定 data-testid 专用属性,只用于测试不参与样式 定位与样式彻底解耦 专属测试属性
等待用 expect 自动重试 waitForTimeout(3000) 网络慢必挂、快了白等 → 改 await expect(el).toBeVisible() 轮询到出现为止 硬等待是 flaky 头号来源 拒绝 sleep
iframe 需先切 frame 在父文档直接找 iframe 内元素必然超时 → 用 page.frameLocator('#editor').getByText('…') 切入再定位,操作完切回主文档 切进去、做完、切回来 先切域再找