ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

嵌入式软件单元测试(十)——嵌入式CI/CD流水线集成单元测试:Jenkins + Ceedling实例

嵌入式软件单元测试(十)——嵌入式CI/CD流水线集成单元测试:Jenkins + Ceedling实例 摘要本文以 Jenkins 和 Ceedling 为例介绍如何在嵌入式 C 项目中搭建集成单元测试的 CI/CD 流水线。文章先分析传统开发模式中测试滞后、回归成本高、环境不一致等痛点以及 CI/CD 带来的快速反馈、质量门禁和可追溯性收益随后讲解 Ceedling 与 Jenkins 的技术选型与环境准备并逐步演示 Ceedling 测试工程的创建、单元测试的编写与本地运行以及 Jenkins 流水线的配置、JUnit 报告输出和结果分析。最后介绍 Docker Agent 环境隔离、代码覆盖率集成和多平台交叉编译等进阶实践并给出常见问题的排查方案帮助团队将单元测试从“事后补救”转变为“持续保障”。1. 引言在嵌入式软件开发中单元测试往往被视为“成本高、收益低”的环节而被推迟甚至省略。然而随着产品复杂度上升、交付节奏加快缺乏自动化测试的嵌入式项目往往在集成阶段暴露出大量缺陷修复成本成倍增长。将单元测试嵌入 CI/CD 流水线是解决这一问题的关键手段。本文以 Jenkins 和 Ceedling 为例介绍如何在嵌入式项目中搭建一条集成单元测试的 CI/CD 流水线。Ceedling 是嵌入式 C 语言项目常用的测试构建框架基于 Unity 和 CMock 提供测试运行与桩代码生成能力Jenkins 则负责流水线编排、定时触发与结果展示。两者结合可以让单元测试在每次代码提交后自动运行并把测试报告反馈给开发团队。2. 为什么嵌入式项目需要 CI/CD 集成单元测试嵌入式项目与纯软件项目相比存在交叉编译、目标板依赖、硬件资源受限等特殊性导致自动化测试落地难度更大。但正因为如此尽早发现问题的价值也更高。2.1 传统开发模式的痛点测试滞后单元测试往往在功能开发完成后才补写甚至直接跳过缺陷在集成阶段集中爆发。回归成本高修改底层驱动或算法后缺乏快速回归手段人工验证耗时且容易遗漏。环境不一致开发者本地环境与 CI 环境差异大导致“本地能过、CI 失败”的尴尬局面。2.2 CI/CD 带来的收益快速反馈每次提交自动触发测试几分钟内即可获知是否引入回归。质量门禁测试失败时阻断合并防止缺陷流入主干。可追溯性测试报告与构建记录关联便于定位问题引入的提交。3. 技术选型Jenkins 与 Ceedling 简介3.1 CeedlingCeedling 是面向嵌入式 C 项目的测试构建系统底层依赖 Unity断言框架、CMock桩代码生成和 Ruby 生态。它通过一个project.yml配置文件管理源码路径、测试路径、编译选项和模拟器设置能够自动发现测试文件并生成可执行测试程序。Ceedling 的核心优势在于自动发现并编译测试文件无需手写 Makefile。内置 CMock自动为外部依赖生成桩函数。支持 GCC 本地模拟运行也可对接模拟器或目标板。输出 JUnit 格式测试报告便于 CI 工具解析。3.2 JenkinsJenkins 是使用最广泛的开源 CI/CD 服务器支持 Pipeline 即代码、分布式构建、丰富的插件生态。对于嵌入式项目Jenkins 可以运行在 Linux 主机上通过 Docker 或 Agent 节点提供交叉编译工具链和测试环境。4. 环境准备4.1 安装 CeedlingCeedling 依赖 Ruby 环境安装命令如下# 安装 Ruby以 Ubuntu 为例 sudo apt-get install ruby-full build-essential 安装 Ceedling gem install ceedling4.2 安装 JenkinsJenkins 的安装方式较多这里以 Docker 方式为例便于快速搭建和迁移docker run -d \ --name jenkins \ -p 8080:8080 \ -p 50000:50000 \ -v jenkins_home:/var/jenkins_home \ -v /opt/embedded-toolchain:/opt/embedded-toolchain \ jenkins/jenkins:lts注意如果项目需要交叉编译工具链需要将工具链目录挂载到 Jenkins 容器中或在 Jenkins Agent 节点上预先安装。5. 创建 Ceedling 测试工程5.1 初始化工程结构在项目根目录执行以下命令生成 Ceedling 标准目录结构ceedling new embedded_ci_demo cd embedded_ci_demo生成的目录结构如下embedded_ci_demo/ ├── project.yml ├── src/ ├── test/ ├── lib/ └── build/5.2 配置 project.yml编辑project.yml配置源码路径、测试路径和编译选项5.3 编写被测模块在src/目录下创建一个简单的计算模块calculator.c和头文件calculator.h5.4 编写单元测试在test/目录下创建测试文件test_calculator.c5.5 本地运行测试在项目根目录执行ceedling test:all如果一切正常会看到类似输出Test test_calculator.c ----------------------- - OVERALL TEST SUMMARY ----------------------- TESTED: 2 PASSED: 2 FAILED: 0 IGNORED: 0 ----------------------- BUILD SUCCESS6. 配置 Jenkins 流水线6.1 创建 Jenkinsfile在项目根目录创建Jenkinsfile定义流水线阶段。这里采用声明式流水线语法6.2 配置 Ceedling 输出 JUnit 报告为了让 Jenkins 能解析测试结果需要在project.yml中启用 JUnit 报告插件:plugins: :load_paths: - #{Ceedling.load_path} :enabled: - report_tests_junit :report_tests_junit: :artifact_filename: report.xml :artifact_path: build/artifacts/test重新运行ceedling test:all会在build/artifacts/test/目录下生成 JUnit 格式的report.xml文件。6.3 在 Jenkins 中创建流水线任务打开 Jenkins 管理界面点击「新建任务」。输入任务名称选择「流水线」类型。在「流水线」配置区域选择「Pipeline script from SCM」。填写 Git 仓库地址和分支脚本路径填写Jenkinsfile。保存并点击「立即构建」触发首次构建。7. 流水线运行与结果分析7.1 触发构建构建触发方式有三种手动触发在 Jenkins 任务页面点击「立即构建」。提交触发配置 Webhook代码推送到 Git 仓库时自动触发。定时触发在 Jenkinsfile 中配置triggers字段例如每晚定时执行。7.2 查看测试报告构建完成后在任务页面点击「测试结果」即可查看 JUnit 报告。Jenkins 会展示测试用例总数、通过数、失败数和跳过数并支持按模块或历史构建对比趋势。7.3 失败定位当测试失败时Jenkins 控制台输出会显示具体失败的断言和堆栈信息。结合 Ceedling 的详细输出可以快速定位到具体测试用例和被测函数。8. 进阶实践8.1 使用 Docker Agent 隔离环境为了保持构建环境一致性可以使用 Docker Agent 运行流水线。在 Jenkinsfile 中指定 Agent 镜像pipeline { agent { docker { image embedded-ci:latest args -v /opt/toolchain:/opt/toolchain } } // ... 其余阶段 }8.2 集成代码覆盖率Ceedling 支持通过 Gcov 生成代码覆盖率报告。在project.yml中启用 gcov 插件:plugins: :enabled: - report_tests_junit - report_build_gcov :gcov: :utilities: - gcovr然后在 Jenkinsfile 中增加覆盖率报告归档步骤stage(Publish Coverage Report) { steps { publishCoverage adapters: [gcovParser(build/artifacts/gcov/**/*.xml)] } }8.3 多平台交叉编译测试对于需要交叉编译的项目可以在 Jenkins 中配置多个 Agent 节点分别对应不同目标平台。在 Jenkinsfile 中使用矩阵Matrix语法并行执行9. 常见问题与排查问题现象可能原因解决方案Jenkins 中找不到 ceedling 命令Ruby 环境未安装或 PATH 未配置在 Jenkinsfile 中显式指定 gem 安装路径或使用 Docker Agent 预装环境测试报告为空JUnit 插件未启用或报告路径配置错误检查 project.yml 中 report_tests_junit 配置确认报告生成路径与 Jenkinsfile 中 junit 路径一致交叉编译工具链无法执行工具链未挂载到 Jenkins 容器或权限不足挂载工具链目录并设置可执行权限或在 Agent 节点上安装工具链CMock 生成桩代码失败头文件依赖缺失或函数原型不完整检查被测模块头文件是否包含完整函数声明必要时在 project.yml 中配置 :cmock 的 :treat_externs 选项10. 总结本文以 Jenkins 和 Ceedling 为例完整演示了嵌入式 C 项目集成单元测试的 CI/CD 流水线搭建过程。核心要点如下Ceedling 负责测试发现、编译、运行和报告生成是嵌入式单元测试的得力工具。Jenkins 负责流水线编排、结果展示和失败通知将测试纳入自动化交付流程。通过 JUnit 报告和覆盖率数据团队可以持续跟踪代码质量变化。使用 Docker Agent 和矩阵构建可以进一步实现环境隔离和多平台并行测试。将单元测试嵌入 CI/CD 流水线并不意味着测试工作量的减少而是把测试从“事后补救”转变为“持续保障”。对于嵌入式团队而言这是一项值得投入的基础设施建设。
返回列表