Skip to content

UI 并行执行与冒烟测试选择 ​

T2-012建议学高级约 60 分钟JDK 21测试专项 B:接口·UI·性能 · UI 自动化

1. 本节定位 ​

《UI 测试稳定性与失败重试边界》解决了"稳定性";本节解决UI 测试最现实的约束:

text
22 个用例 → 168 秒(串行)        ← 还能忍
500 个用例 → 63 分钟              ← 没人等了 ✗✗

UI 测试太慢,而"慢"会直接导致"没人跑" ✓ ——所以提速是必答题 ✓

本节讲三个手段,其中只有一个真正常用 ✓✓:

手段效果代价
① 少测一点(冒烟集)★★★最有效 ✓需要判断"哪些最该测" ✓
② 并行 ★★取决于机器 ⚠️成倍占用资源 ✗(本节实测:本机反而更慢)
③ 用接口准备数据 ★★★大幅减少 UI 操作 ✓需要接口测试能力 ✓

2. 学习目标 ​

  • 说出 UI 提速的三个手段与优先级 ★★★;
  • 知道冒烟集怎么选(四条判据)★★★;
  • 知道并行的前提(用例必须独立)★★★;
  • 知道并行的代价,并能判断"该不该开" ★★★(含本轮的反直觉实测);
  • 会配置 JUnit 5 的并行执行 ★★;
  • 知道UI 测试的执行时机该怎样分层 ★★。

3. 前置知识检查 ​

  • 完成 T2-011 的 flaky 排查了吗?✓
  • 知道测试分层的思路吗?(T2-004)✓

4. 为什么需要这个知识 ​

先看一个"UI 测试被放弃"的典型过程 ✗:

text
第 1 周:20 个 UI 用例,跑 3 分钟 → 每次提交都跑 ✓
第 4 周:80 个用例,跑 12 分钟 → 改成每晚跑一次 ⚠️
第 8 周:200 个用例,跑 30 分钟 → 每晚跑不完,改成每周 ⚠️
第 12 周:没人记得它还在跑 ✗✗

★ 关键数字在哪 ✓:

超过 10 分钟,人就不愿意等了 ✓(T2-004 5.6①)✓

所以 UI 测试的用例数必须有"预算" ✓✓

本项目的量级感受:

text
22 个 UI 用例 → 168 秒(串行)       ← 单类测试尚可,全量提交前跑一次可接受

5. 核心概念 ​

5.1 手段一:冒烟集 —— 最有效的提速 ★★★ ​

核心思想:不是"跑得快点",而是"少跑一点" ✓✓

★ 冒烟集怎么选(四条判据):

#判据例子
① 覆盖关键用户路径 ★★★能走通的"主流程"打开页面 → 创建 → 列表可见 → 删除 ✓
② 每个模块最多 1~2 条 ★★不全覆盖,只"探活"订单模块 2 条,不做边界
③ 快 ★★单条 < 30 秒不做多步流程 ✓
④ 稳定 ★★★不能有 flaky有 flaky 的先修或隔离

★ 一句话概括冒烟集:

它回答"系统是不是基本能用",不回答"功能是否完全正确" ✓✓

后者的任务是回归测试(可以慢、可以低频) ✓

本项目的冒烟集(UiSmokeTest,@Tag("smoke"))✓:

用例覆盖
smoke_01_home_page_loads页面能打开、标题对 ✓
smoke_02_async_panel_loads异步区块能加载(等待正确)✓
smoke_03_list_renders_rows列表能渲染数据 ✓
smoke_04_create_appends_row创建后能看到新行 ✓
smoke_05_delete_removes_row删除后行消失 ✓
non_smoke_secondary_path不进冒烟集(次要路径)✓

实测规模:

text
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 36.66 s
  --- in cn.kb.learn.ui.UiSmokeTest

★ 六个用例 36.66 秒 = 平均 6.1 秒/条 ✓ ——符合"每条 < 30 秒"的标准 ✓

★ 用一个标签就把"冒烟"与"全量"分开了 ✓:

java
@Tag("ui")
@Tag("smoke")
class UiSmokeTest { ... }
powershell
pwsh -File scripts\ui-test.ps1 -Smoke      # 只跑冒烟集
pwsh -File scripts\ui-test.ps1             # 跑全部 UI

5.2 手段二:并行 —— 不一定更快 ★★★ ​

并行的前提:用例之间必须彼此独立 ✓✓

前提不满足的后果
不共享数据 ★★★互相改对方的列表 → 断言失败 ✗(T2-011 的真实案例)
不共享浏览器实例 ★★操作互相干扰 ✗
不依赖执行顺序 ★★★顺序一变就失败 ✗
不抢同一份外部资源 ⚠️比如同一个测试账号、同一个库存 ✗

★ 配置方式(JUnit 5,本项目已配好)✓:

properties
# junit-platform.properties
junit.jupiter.execution.parallel.enabled=false        # 默认关:并行不是免费的
junit.jupiter.execution.parallel.mode.default=same_thread
junit.jupiter.execution.parallel.mode.classes.default=concurrent
junit.jupiter.execution.parallel.config.strategy=fixed
junit.jupiter.execution.parallel.config.fixed.parallelism=4
powershell
pwsh -File scripts\ui-test.ps1 -Parallel                 # 4 线程
pwsh -File scripts\ui-test.ps1 -Parallel -Parallelism 2  # 指定线程数

★★★ 本轮的实测:并行反而更慢 ✓✓✓

串行并行(4 线程)
用例数2222
总耗时167.96 s302.35 s ✗✗
驱动实例1 个4 个
msedge 进程峰值约 8 个17~24 个 ⚠️
各测试类耗时50.58 / 29.70 / 21.42 / 36.66 / 29.60 s76.27 / 52.49 / 42.46 / 72.39 / 58.74 s

★ 每个测试类都变慢了 30%~70% ✓ ——总时间增加了 80% ✗✗

原因:

4 个浏览器实例在同一台机器上争抢 CPU 与内存 ✓

这与 T2-003 的"同机压测"是同一个道理 ——资源不是无限的 ✓✓

★ 附带发现:并行的报告会"归类错乱" ✓✓✓

text
串行报告:
  OrderLocatorTest        5 个      ← 实际就是 5 个 ✓
  UiEnvironmentCheckTest  3 个      ← 实际就是 3 个 ✓

并行报告:
  OrderLocatorTest        1 个      ✗ 归属错了
  UiEnvironmentCheckTest  10 个     ✗ 归属错了
  (总数仍是 22 ✓)

为什么:并行执行时,测试事件的"归属类"是按"完成的线程上下文"记录的 ✗ —— 于是"5 个"被算到了别的类头上 ✓

★ 这个发现很实用:

并行会让"按类统计"的报告失真 ✓ —— 排查"哪个类挂了"时不要只看报告的分类数字 ✓✓

这也是"报告要能自证"的又一例(T2-017 5.2)✓

★★ 那到底该不该开并行 ✓:

情况建议
单机、资源一般(本项目的位置)不开 ✗ ——开了更慢 ✓
多核大内存的 CI 机器开,但要先实测 ✓
用例之间不独立先修隔离,再谈并行 ✗✗
任何情况先测再开,不要假设"并行=更快" ✓✓

5.3 手段三:用接口准备数据 ★★★ ​

这是"提速"里最容易被忽略、但收益最大的一招 ✓✓

问题:很多 UI 用例的前置步骤是"造数据" ✗ ——而造数据本来就不需要经过界面 ✗✗

对比:

java
// ✗ 用 UI 造数据:每次创建要走"打开页面 → 填表 → 提交 → 等跳转"
for (int i = 0; i < 5; i++) {
    page.createOrder("商品" + i, "1", "地址" + i);     // 每次约 6 秒 → 30 秒 ✗
}

// ✓ 用接口造数据:一次 HTTP 请求
for (int i = 0; i < 5; i++) {
    given().contentType(JSON)
        .body("{\"productId\":\"P-" + i + "\",\"quantity\":1,\"address\":\"地址\"}")
    .when().post("/api/orders");                        // 每次约 0.1 秒 → 0.5 秒 ✓✓
}

★ 提速约 60 倍 ✓ ——而且不碰界面,也就不会因界面变化而失效 ✓✓

★ 这个做法的原则:

UI 测试只该验证"界面能否呈现",不该负责"把数据准备好" ✓✓

数据准备交给接口(T2-005),UI 只做"看一眼" ✓

★ 本项目已经在用这个思路 ✓:

  • UI 测试里的"初始 2 条订单" 是 UiPageController 构造时创建的(相当于夹具)✓
  • 冒烟④ 创建后能看到新行 用的是 UI(因为"创建交互"本身就是要测的 ✓)
  • 而"要 5 条数据"这类前置,应该走接口 ✓

5.4 执行时机:给 UI 测试分层 ★★ ​

UI 测试不能"每次提交都全量跑" ✗ ——所以要给它排班 ✓:

时机跑什么预期时长
每次提交(PR) ★冒烟集 ✓< 1 分钟
合并到主干 ★全量 UI ✓3~10 分钟
每晚 ★★全量 UI + 跨浏览器(如需)30 分钟+

★ 这与 T2-004 的分层思路完全一致 ✓:

能快的地方快,该慢的地方慢慢跑 —— 关键是"让快的先给结论" ✓✓

★ 本项目现在的流水线还没有 UI 层 ✗ ——因为 UI 需要额外的环境准备(启动应用) ✓ 这也是 scripts/ui-test.ps1 单独存在的原因 ✓✓

6. 递进示例 ​

6.1 最小示例:给用例打标签 ​

java
@Tag("smoke")
@Test
void smoke_01_home_page_loads() { ... }

6.2 业务示例:两种运行模式 ​

powershell
scripts\ui-test.ps1 -Smoke        # 冒烟:约 37 秒
scripts\ui-test.ps1               # 全量:约 168 秒
scripts\ui-test.ps1 -Parallel     # 并行:约 302 秒(本机反而更慢)✗

6.3 反例:默认就用并行 ​

java
junit.jupiter.execution.parallel.enabled=true     // ✗ 没实测过就开

7. 完整可运行代码与实测 ​

测试代码:

  • labs/ui-testing/src/test/java/cn/kb/learn/ui/UiSmokeTest.java(冒烟集,@Tag("smoke"))
  • labs/ui-testing/src/test/resources/junit-platform.properties(并行配置)

入口:scripts/ui-test.ps1(支持 -Smoke / -Parallel / -Parallelism)

★ 实测一:串行全量 ✓

text
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 50.58 s -- OrderLocatorTest
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 29.70 s -- OrderPageObjectTest
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 21.42 s -- UiEnvironmentCheckTest
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 36.66 s -- UiSmokeTest
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 29.60 s -- UiStabilityTest

合计:22 个用例,167.96 秒(约 2.8 分钟)

★ 实测二:并行(4 线程) ✗

text
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 76.27 s -- OrderLocatorTest
Tests run: 5, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 52.49 s -- OrderPageObjectTest
Tests run: 10, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 42.46 s -- UiEnvironmentCheckTest
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 72.39 s -- UiSmokeTest
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 58.74 s -- UiStabilityTest

合计:22 个用例,302.35 秒(约 5 分钟)

★★ 三个可以直接写进报告的结论 ✓:

#结论依据
①本机上并行让 UI 测试慢了 80%167.96 s → 302.35 s ✗
②并行的代价是"成倍的浏览器进程"1 个驱动 → 4 个驱动;8 个 msedge → 17~24 个 ⚠️
③并行的报告"按类统计"会失真OrderLocatorTest 从 5 变 1、UiEnvironmentCheckTest 从 3 变 10 ✗(总数仍 22 ✓)

★ 实测三:冒烟集单独跑 ✓

text
Tests run: 6, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 36.66 s

冒烟集 36.66 秒 vs 全量 167.96 秒 ✓ ——只跑 27% 的用例,用了 22% 的时间 ✓✓

★ 这才是"提速"的正解:

不是"更快地跑全部",而是"只跑最有价值的那部分" ✓✓

8. Debug 观察点 ​

  1. 并行跑时打开任务管理器:观察 msedge 进程数(本机到过 24 个)★★;
  2. 对比并行与串行的报告:观察"用例数归属"的差异 ★★★;
  3. 用 -Parallelism 2 再跑一次:观察是否比 4 线程更快(提示:可能更快,因为争抢变少)★;
  4. 统计冒烟集与全量的耗时比:算"用多少时间换多少覆盖" ✓;
  5. 把一个用例改成"依赖前一个用例",再开并行:观察它开始随机失败 ★★。

9. 常见错误 ​

#错误说明
1以为"并行 = 更快" ✗✗本轮实测反例:慢了 80% ✗✗
2用例不独立就开并行 ✗✗随机失败(T2-011)✗✗
3冒烟集选得太多 ✗从 37 秒变 3 分钟,就没人跑了 ✗
4冒烟集里放 flaky 用例 ✗✗每次都红,团队学会忽略 ✗✗
5用 UI 造数据 ✗✗慢 60 倍(5.3)✗✗
6看并行的"按类统计"排查问题 ⚠️归属失真(5.2)✗
7每次提交都跑全量 UI ✗拖垮反馈速度(5.4)✗

10. 动手实验 ​

目标:亲手测出"并行到底更快还是更慢"。

步骤:

  1. 串行跑一次,记录总耗时(本项目约 168 秒)✓;
  2. 并行 4 线程跑一次,记录总耗时(本项目约 302 秒)✗;
  3. 并行时观察 msedge 进程数,与串行对比 ★;
  4. 用 -Parallelism 2 再跑一次,看是否比 4 线程更优 ★★;
  5. 只跑冒烟集,记录耗时(本项目约 37 秒)✓。

验收方式:能说出"你这台机器上,并行比串行快还是慢、为什么"。

扩展任务:找出"最适合本机的并行度":

  • 依次测 1 / 2 / 4 / 8 线程 ✓;
  • 画出"并行度 → 总耗时"的曲线 ★;
  • 说明:为什么曲线会先降后升(提示:资源竞争超过收益的临界点,与 T2-003 的吞吐拐点是同一个形状)✓✓

11. 练习题 ​

  1. 判断:UI 测试开启并行一定能缩短总耗时。(对 / 错)
  2. 填空:UI 提速的三个手段按有效性排序是 ______ > ______ > ______。
  3. 简答:为什么"用接口造数据"能提速几十倍?
  4. (代码阅读)某项目把 80 个 UI 用例全部打上 @Tag("smoke"),然后让 PR 流水线跑冒烟集。有什么问题?
  5. (编程)给 ui-test.ps1 加一个 -Jobs <n> 参数,自动跑多个并行度并输出耗时对比表(便于找出本机最佳并行度)。
参考答案(要点)
  1. 错。本轮实测:本机并行反而慢了 80% ✗ ——因为 4 个浏览器实例争抢资源 ✓(5.2)
  2. 冒烟集(少测一点)> 用接口准备数据 > 并行 ✓(有效性排序,并行的效果取决于机器 ✓)
  3. 因为绕过了"浏览器 + 协议 + 驱动"这条长链 ✓ ——一次 HTTP 请求约 0.1 秒,而一次 UI 操作约 6 秒 ✓(5.3)
  4. 冒烟集失去意义 ✗ ——80 个用例的冒烟集跑起来还是要十几分钟,PR 门禁会被拖垮 ✓ —— 冒烟集的价值恰恰在于"少" ✓★
  5. 要点:循环不同并行度、记录耗时、输出表格 ✓ ——本质是找"吞吐拐点"(T2-003)✓

12. 掌握标准 ​

  • [ ] 能说出三个提速手段及其有效性排序 ★★★;
  • [ ] 会选冒烟集(四条判据) ★★★;
  • [ ] 知道并行的前提是用例独立 ★★★;
  • [ ] 知道并行不一定更快,并能用数据判断 ★★★;
  • [ ] 知道并行会让"按类统计的报告"失真 ★★;
  • [ ] 会用接口准备数据代替 UI 造数据 ★★★;
  • [ ] 知道 UI 测试的分层执行时机 ✓。

13. 扩展资源 ​

14. 下一步学习 ​

UI 自动化五节(T2-002 / T2-009 / T2-010 / T2-011 / T2-012)到此完成。

TB 模块剩余:

之后回到主线的 S2 / S4 / S5 等阶段(见 matrix.md)。

进度只保存在本机浏览器,可随时清除

个人学习项目:AI 生成内容均经人工复核,第三方资源仅作索引