摘要:本文是 BSP 系列第 45 篇,聚焦 Regression Test(回归测试)。文章首先厘清 Build Test、Functional Test 与 Regression Test 的区别,指出 Regression 的本质是对历史已验证功能的持续重复验证;随后给出 BSP Regression 的 11 层测试树与"可重复"第一原则,强调 Test Case ID 与稳定结果追踪的重要性。接着深入探讨 Driver Regression 的测试维度、间接破坏的发现价值、Full vs Targeted Regression 的取舍,并给出公司 BSP 推荐的两级 Regression 流程(Fast + Full)。最后覆盖 Regression Matrix、失败信息规范、Regression History、Git Bisect 搭配、测试目录设计、Twister 与 HIL 集成,以及"测试金字塔"与 Host/Target 分层原则,帮助 BSP 从"能用"走向"可长期维护"。
**BSP Regression Test
**
那么第 45 篇自然要解决一个更实际的问题:
BSP 今天能跑,不代表下周还能跑。
Regression Test 的任务,就是发现"以前能工作的东西,现在被改坏了"。
一、Regression Test 到底是什么?
先区分三个概念。
Build Test
代码 ↓ 编译 ↓ 成功?它只能回答:
“这份代码现在能不能编译?”
Functional Test
例如 UART:
UART Driver ↓uart_configure()↓uart_tx()↓ UART 输出测试:
UART TX"hello"↓ 收到 hello ↓ PASS它回答:
“这个功能现在能不能工作?”
Regression Test
Regression Test 问的是:
“以前已经验证过的功能,在这次修改之后有没有被破坏?”
例如:
v1.2GPIO PASS UART PASS SPI PASS I2C PASS Timer PASS Interrupt PASS Boot PASS Flash PASS然后你修改了 Clock Driver。
重新测试:
Clock PASS GPIO FAIL ← 被间接破坏 UART FAIL SPI PASS I2C FAIL这就是 Regression。
二、BSP Regression Test 的核心思想
一个成熟 BSP 不应该只有:
build.sh而应该逐渐形成:
BSP │ ├── Build Tests │ ├── Unit Tests │ ├── Driver Tests │ ├── Integration Tests │ ├── Boot Tests │ ├── HIL Tests │ └── Regression Tests注意:
Regression Test 不是某一种测试。
它实际上是一个测试策略:
已有测试集合 │ ↓ 每次代码变化重新执行 │ ↓ 比较结果 │ ↓ 发现 Regression所以可以理解成:
Regression = 对历史上已经通过的测试进行持续重复验证。
三、BSP Regression 最重要的测试层次
我建议公司的 BSP 最终形成下面这棵树:
BSP Regression │ ├──1.Build Regression │ ├──2.Devicetree Regression │ ├──3.Kconfig Regression │ ├──4.Driver Regression │ ├── GPIO │ ├── UART │ ├── SPI │ ├── I2C │ ├── Timer │ ├── PWM │ └── ADC │ ├──5.Interrupt Regression │ ├──6.Clock/Reset Regression │ ├──7.Boot Regression │ ├──8.Power/Sleep Regression │ ├──9.SMP/Multi-core Regression │ ├──10.HIL Regression │ └──11.Release Regression不是每个 SoC 都必须全部拥有。
例如一个简单 Cortex-M4:
GPIO UART SPI I2C Timer Interrupt Clock Boot Flash已经足够构成第一版 Regression Suite。
四、第一原则:Regression Test 必须"可重复"
这是 BSP Regression 最容易犯的错误。
比如:
UART test 打开串口工具 手工输入 hello 看看有没有输出这个叫:
Manual Validation
不是好的 Regression Test。
因为 CI 无法可靠判断:
PASS/FAIL真正的 Regression Test 应该:
Flash firmware ↓ Reset ↓ Board boot ↓ Run test ↓ Generate machine-readable result ↓ PASS/FAIL例如:
BOOT:PASS UART:PASS GPIO:PASS SPI:PASS I2C:PASS TIMER:PASS IRQ:PASS最终:
REGRESSION: PASS五、Regression Test 最重要的设计:Test Case ID
不要只写:
test_uart test_gpio公司 BSP 应该给测试建立稳定 ID。
例如:
BSP-BOOT-001BSP-IRQ-001BSP-GPIO-001BSP-GPIO-002BSP-UART-001BSP-UART-002BSP-SPI-001BSP-I2C-001BSP-TIMER-001例如:
BSP-UART-001Name:UART basic TX Board:company_board_a Peripheral:UART0 Expected:"HELLO_BSP"Timeout:2sec这样以后:
v1.0v1.1v1.2v1.3都可以追踪:
BSP-UART-001v1.0PASS v1.1PASS v1.2PASS v1.3FAIL这就开始具有真正的 Regression 能力了。
六、Test Case 不应该只测试"Happy Path"
例如 UART:
最简单的是:
UART TX
但成熟 Regression 应该逐渐增加:
UART │ ├── TX ├── RX ├── TX/RX ├── baudrate ├── parity ├── stop bits ├── FIFO ├── interrupt ├── timeout └── error handling例如:
BSP-UART-001Basic TX BSP-UART-002Basic RX BSP-UART-003TX/RX loopback BSP-UART-004IRQ RX BSP-UART-005Different baudrate七、Driver Regression 应该测试什么?
以 GPIO 为例。
不要只测试:
gpio_pin_set();而应该考虑:
GPIO Regression │ ├── output high ├── output low ├── input ├── pull-up ├── pull-down ├── interrupt ├── rising edge ├── falling edge └── polarity测试关系:
Devicetree │ ↓ GPIO Controller │ ↓ GPIO Driver │ ↓ Zephyr GPIO API │ ↓ Test Application这样才能发现:
DT 改了 ↓ GPIO base address 错了 ↓ Driver 仍然编译成功 ↓ HIL Regression FAIL这类问题单纯 Build Test 根本抓不到。
八、Regression 最有价值的地方:发现"间接破坏"
这是 BSP Regression 最重要的价值之一。
假设你修改:
Clock Driver你可能只修改:
drivers/clock_control/
但是:
Clock │ ├── UART ├── SPI ├── I2C ├── Timer └── PWM所以:
Clock change ↓ UART frequency wrong ↓ UART test FAIL这就是:
Regression Dependency
因此 BSP 的 Regression Test 本质上是在保护:
硬件依赖关系九、不要只测试"改动的 Driver"
例如 Git diff:
drivers/clock_control/company_clock.c错误思路:
只跑 Clock Test更合理:
Clock changed ↓ Run Clock tests ↓ Run dependent driver tests ↓ Run boot test ↓ Run smoke test也就是:
Changed component ↓ Dependency graph ↓ Affected tests十、这就和前面的 Devicetree Dependency Graph 联系起来了
我们之前讲过:
UART │ ├── Clock ├── Pinmux └── IRQRegression 可以反过来利用这个关系:
修改 Clock │ ├── UART ├── SPI ├── I2C └── Timer │ ↓ Regression所以未来成熟 BSP CI 可以做到:
Git diff ↓ Changed files ↓ Affected drivers ↓ Affected tests ↓ Run targeted regression这叫:
Test Impact Analysis
十一、Full Regression vs Targeted Regression
这两个一定要区分。
Full Regression
所有测试:
1000tests全部执行。
优点:
覆盖全面缺点:
时间长例如:
30min1hour3hoursTargeted Regression
假设修改:
drivers/serial/那么:
UART tests Boot tests Console tests 相关 HIL tests优先执行。
例如:
1000tests ↓ 分析影响 ↓120tests下面用一张表格从五个维度对比两者:
| 维度 | Full Regression | Targeted Regression |
|---|---|---|
| 执行范围 | 全部测试(如 1000 tests) | 仅受影响的相关测试(如 120 tests) |