测试_05:自动化测试与 CI——把测试塞进流水线
2026/8/25 13:37:52 网站建设 项目流程

适用人群:单元测试写了几个,但每次都是"手动在 PC 上跑一下看看",改了十处代码才想起来"好像该跑一下测试",结果早崩了都不知道的同学。这是16_嵌入式测试软件篇的收口文。
上篇测试_04解决了"测依赖硬件的代码",这篇解决"怎么让测试自动、持续地跑",把前面 02/03/04 串成一条流水线。
读完你能得到:
① 为什么手工测不靠谱,CI 是什么;
② 用 GitHub Actions / 本地脚本,提交即跑测试;
③ 静态检查(测试_03)怎么挂进同一条流水线;
④ 代码覆盖率 gcov/lcov 白话版,以及它的陷阱;
⑤ 嵌入式怎么做:PC 测逻辑 + 板子只跑冒烟。


一、手工测的痛

假设你现在的状态:本地有一套 Unity 测试,平时这么用——

gcc utils.c test_utils.c unity.c-otest_utils&&./test_utils

看起来没问题。但真实情况是:

  1. 忘了跑:改完代码直接提交,测试压根没跑,bug 跟着进了仓库。
  2. 只在自己机器跑过:你的环境能过,同事的机器编译器版本不同,一拉就红。
  3. 没标准:什么叫"测过了"?你心里有数,但流水线不知道。

CI(持续集成,Continuous Integration)就是来解决这个的:你一提交代码,服务器自动拉下来、编译、跑测试、跑静态检查,红了当场告诉你

一句话:手工测靠自觉,CI 靠流程。自觉会忘,流程不会。


二、CI 长什么样(以 GitHub Actions 为例)

最精简的 CI 配置(.github/workflows/test.yml):

name:embedded-testson:[push,pull_request]jobs:test:runs-on:ubuntu-lateststeps:-uses:actions/checkout@v4-name:编译并跑单元测试run:|gcc utils.c test_utils.c unity.c -o test_utils ./test_utils-name:静态分析run:|cppcheck --error-exitcode=1 --enable=all --std=c99 src/

这段代码的意思是:每次 push 或开 PR,GitHub 的服务器就自动做这两件事。任何一步非零退出,整个 CI 标红,提交被拦下。

没有 GitHub 也没关系。本地用个Makefile+ 一句make test也行,关键是"一键跑全部检查",而不是手动敲三条命令。下面给个最小 Makefile:

CC = gcc SRC = utils.c test_utils.c unity.c test: $(CC) $(SRC) -o test_utils && ./test_utils static: cppcheck --error-exitcode=1 --enable=all --std=c99 src/ check: test static

make check一条命令,单元测试 + 静态分析全跑。把"测试"变成肌肉记忆。


三、把静态检查挂进来(呼应测试_03

测试_03讲的-Wall -Werror+ cppcheck,正好作为 CI 的第一、二关:

# 第一关:警告清零(任何 warning 都编不过)gcc-Wall-Wextra-Werror-csrc/*.c# 第二关:静态分析(发现潜在 bug / 违反规范)cppcheck --error-exitcode=1--enable=all--std=c99 src/# 第三关:单元测试(验证行为正确)./test_utils

三关全过,代码才算"健康"。这就是把"代码质量"从靠人盯变成靠机器卡

面试时这句特别好使:"我们工程的 CI 三关——编译零警告、cppcheck 静态分析、Unity 单元测试,任何一关红都合不进去。"这比"我写完了会 review"专业太多。


四、代码覆盖率:你的测试到底覆盖了多少

覆盖率工具回答一个问题:“你写的测试,跑到了多少行代码?”GCC 用 gcov、配合 lcov 出报告:

# 编译时插桩gcc--coverageutils.c test_utils.c unity.c-otest_utils# 跑测试./test_utils# 生成报告gcov utils.c# 命令行看每行是否被覆盖lcov--capture--directory.--output-file cov.info genhtml cov.info --output-directory cov_html# 生成网页报告

报告会告诉你:哪些函数 100% 覆盖,哪行if分支从来没被测到。

💡 覆盖率是个"下限指标":低覆盖率一定说明测少了,但高覆盖率不代表测对了。见过有人为了冲 100% 写TEST_ASSERT_TRUE(1)这种无效断言——跑通了但什么都没验证。别这么干。

覆盖率的陷阱

陷阱说明
追求 100%边际成本高、收益低,核心逻辑覆盖到就行
无效断言冲覆盖率TEST_ASSERT_TRUE(1)跑通但没验证行为
只看行覆盖不看分支一行代码但if/else只测了一半,分支没覆盖

五、嵌入式怎么做:PC 测逻辑,板子只跑冒烟

回看测试_01说的"把硬件无关逻辑抽到 PC 上测"。落到 CI 上就是两类测试分开

CI 自动跑(每次提交): ├─ PC 单元测试:算法/协议/状态机(Unity,秒级) └─ 静态分析:cppcheck + 编译零警告 板端手动/定期跑(烧录后): └─ 冒烟测试:上电能起、关键功能能用(见 `测试_06~10`)

MCU 上跑不了庞大的测试框架,也跑不了 gcov,所以逻辑全在 PC 的 CI 里验,板子只做"能不能起来"的冒烟。这是嵌入式测试最务实的分工。

这套分工直接对应前面几篇:测试_02/04的逻辑测试在 PC,测试_06~10的板级/系统测试在硬件上。


六、新手必踩的坑

#后果正确做法
1CI 挂了没人看等于没挂红了就挡合入,强制修
2只在自己机器测过别人一拉就红用 CI 在干净环境跑
3覆盖率凑数假安全断言要真验证行为
4把所有测试塞板子慢、难维护PC 测逻辑、板子只冒烟
5测试不独立顺序一变就挂每个测试 setUp/tearDown 复位

七、总结(软件测试 5 篇收口)

主题一句话
01总览测试是预防,调试是救火
02单元测试Unity 在 PC 上测纯函数
03静态分析不运行也能找 bug,MISRA 兜底
04桩/模拟用接口抽象 + 桩顶掉硬件依赖
05自动化/CI提交即跑,覆盖率看覆盖

一句话总结:手工测靠自觉会忘,CI 把"编译零警告 + 静态分析 + 单元测试"串成流水线,红了就挡合入;嵌入式是"PC 测逻辑、板子只冒烟",覆盖率看下限不迷信 100%。


CI 平台不限于 GitHub Actions,GitLab CI、本地 Makefile 思路一致;gcov/lcov 是 GCC 配套工具,搜 “gcov lcov 教程” 即可上手。覆盖率数据以你项目的实际配置为准。
本站相关:测试_01~04(软件测试前四篇)、测试_03(静态分析)、测试_06(硬件测试起手)。


下一篇:测试_06_上电与电源测试——电压电流纹波功耗怎么量

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询