《测试驱动的嵌入式C语言开发》——2.2节Unity:一个全部用C实现的自动化测试框架

简介: 本节书摘来自华章社区《测试驱动的嵌入式C语言开发》一书中的第2章,第2.2节Unity:一个全部用C实现的自动化测试框架,作者:(美)James W. Grenning,更多章节内容可以访问云栖社区“华章社区”公众号查看

2.2 Unity:一个全部用C实现的自动化测试框架
Unity是一个简单且直接的自动化单元测试框架。它由很少的几个文件构成。让我们通过几个示例单元测试用例来认识一下Unity和单元测试。如果你是一个长期的Unity用户,你会发现如果不用Unity所提供的脚本来生成测试运行容器,那么额外的几个宏可能会很有帮助。
用Unity写的sprintf()测试用例
测试要写得短并且有重点。可以把它想象成一个安检过程,通过时保持安静,失败时就要发出警报声。下面这个测试让sprintf()处理一个没有格式操作的格式声明。


e0e4e59586e7f7fb62b6f31fb0a4feaeab99a0e3

宏TEST()用来定义一个测试函数,当运行所有测试的时候就会调用它。第一个参数是一个测试的组名。第二个参数是这个测试的名字。我们将在第3章中更仔细地介绍TEST()这个宏。
宏TEST_ASSERT_EQUAL()用来比较两个整数。sprintf()应该返回给测试说它格式化的结果字符串长度为3,并且如果是这样的,TEST_ASSERT_EQUAL()就成功了。像大多数的自动化测试框架一样,TEST_ASSERT_EQUAL()的第一个参数是期望中的值。
TEST_ASSERT_EQUAL_STRING()用来比较两个以null结尾的字符串。这句话是声明output的内容必须是字符串“hey”。按照习惯,第一个参数是期望值。
如果任意一个检查的条件不满足,测试就会失败。这些检查会按顺序进行,TEST()会在碰到第一个失败时终止。
注意,TEST_ASSERT_EQUAL_STRING()可能在意外的情况下通过。如果output的内容刚好本来就是“hey”,那么如果sprintf()什么也不干,这个测试也会通过。当然,这不大可能发生,但我们最好还是改进一下这个测试,把output初始化成一个空字符串。


237d19ee72585f954c1d15c8f9fa51047b32b555


a90c9ec98c318e3f80e202cd4fb29c38c18c9937

如果我们担心sprintf()会破坏output之前的内存,我们也可以把output的大小再加一个字符,然后把&output[1]传给sprintf()。最后检查一下output[0]是否还是0xaa,这在很大程度上能证明sprintf()的行为是正确的。
在C语言中,要让测试面面俱到很难。错误的或是恶意的代码可以在output之后或之前距离很远的地方搞破坏。把测试做到什么程度是需要我们自己来判断的。后面你将会看到在TDD中如何决定要写哪些测试。
在以上的测试中,你可以看到其中正在滋生一些细微的重复。output的声明是重复的,初始化是重复的,以及对写过界的检查也是重复的。如果只有两个测试,可能问题不大,但如果你刚好是维护sprintf()的人,你需要比这多得多的测试。随着测试的增加,这些重复会越来越多并且让测试用例中的代码难以理解。接下来让我们看一看测试夹具是如何帮我们避免TEST()测试用例中的重复的。
Unity中的测试夹具
使用测试夹具的目的是避免重复。测试夹具把所有测试都需要的那些部分组织在一处。请留意以下对sprintf()测试的代码中是如何使用TEST_SETUP()和TEST_TEAR_DOWN()来避免重复的。


8bbd52bba36aeb0ca3228668ab32e767a09ac5d1


6f6f2c05fd09db39fd8e5595c3710cdd7426d1ea

在TEST_GROUP()之后定义的共享数据会在TEST_SETUP() 中进行初始化,TEST_SETUP() 将在每个TEST()的起始大括号之前执行。这些数据在源文件内可见,而且可以被源文件内的TEST() 和辅助函数使用。在我们的这个TEST_GROUP()组中不需要在TEST_TEAR_DOWN()中做任何清理工作。
作用域为源文件的辅助函数expect()和 given()会帮助sprinitf()的测试保持整洁和不重复。
说到底,这就是普通的C代码,所以你可以任意使用共享数据和辅助函数。我给出的是一种典型的结构,用于有共享数据和检查条件的一组测试。
现在这些测试更专注、简约、直接、能说明问题。

你会发现,一旦你理解了一个特定的TEST_GROUP()并且看过了几个例子以后,要想写出下一个测试用例会简单很多。当一个TEST_GROUP() 中有一个共同的模式时,每个测试都变得很容易阅读、理解和拓展。
安装Unity测试
从前面的例子中很难看出测试用例是如何运行并使用必要的前置和后置过程的,而这是通过另一个叫TEST_GROUP_RUNNER()的宏来完成的。TEST_GROUP_RUNNER()可以和测试放在一起,也可以放在不同的文件里。为了避免总是要在同一文件里上下滚动,本书使用了不同的文件。对于sprintf()的两个测试,TEST_GROUP_RUNNER()看起来如下所示:


77772f6ad085ad91dc419bc12ddd43d4824e7091

每个测试用例都通过RUN_TEST_CASE()宏来调用。基本上就相当于RUN_GROUP_RUNNER()会依次调用以下这些函数体:


2c7a6051da737b44fc1fc2fb274273783bb1698c


e898a6593886e7abdbab6c1986b5ec87460e186e

RUN_TEST_GROUP(测试组名)会调用由TEST_GROUP_RUNNER()定义的函数。所以每个你希望main()来运行的TEST_GROUP_RUNNER()都要加上一个RUN_TEST_GROUP。请注意,一定要把RunAllTests()传给UnityMain()函数。
使用纯C实现的测试框架比较遗憾的一点是,你要记得把每个TEST()加到TEST_GROUP_RUNNER()中,并且整个容器将被UnityMain()函数调用。如果你忘了,测试会被编译但不会执行,可能出错了你也不会知道。
因为存在这种可能出错的情况,所以Unity设计者创建了一个代码生成系统,可以读取你的测试文件并生成测试容器代码。为了让刚开始使用时减少对Unity的依赖,我将不会使用代码生成脚本,而是手工把测试代码串联起来。
在下一节我们介绍CppUTest时,你会看到这个问题的另一种解决办法。在这之前先让我们来看看Unity的输出。
Unity的输出
测试的运行应该作为测试自动构建的一部分。应该用一个简单的命令就可以构建并运行构建出来的测试可执行程序。你会发现我经常构建,每次小的改动后都会重新构建。这就是TDD。我把我的开发环境设置成每次我保存一个文件时就会自动构建所有的东西。测试的输出就像这样:


d7e5b932d4dac4768963ac111628ad1694afa5be

请注意,在所有测试都通过时,输出最少。随便瞟一眼,如果看到一行写着“OK”的文字,这意味着“所有测试通过”。这符合UNIX风格,测试框架遵循“没有消息就是最好的消息”原则(稍后你会看到,当有测试失败时它会给出特定的错误信息)。它看上去很直白,但还是让我们来看看每行输出都是什么含义。
请注意,每个测试用例运行时都会打印出一个点(.)。如果测试运行起来时间很长,这会让我们感知到有东西在运行。分隔符(---)那一行只是用来分隔测试的总结。
Tests—总共的TEST()个数。
Failures—失败的TEST()的个数。
Ignored—处在忽略状态的测试的个数。忽略的测试会被编译但不会执行。
让我们加一个出错的测试来看看会发生什么。看看测试的输出,我们故意加的错误应该很明显:


e4fa2052f0d0c747a02d54be63cfe6e45a20891a

失败信息会报告失败的测试用例所在的文件名和行号、测试用例的名字,以及为什么会失败。并且请留意最后的总结中显示一个测试失败了。
你可以在附录B中找到更多关于Unity的信息。

相关文章
|
3月前
|
数据采集 算法 测试技术
【硬件测试】基于FPGA的1024QAM基带通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的1024QAM基带通信系统的硬件测试版本,包含testbench、高斯信道模块和误码率统计模块。系统新增ila在线数据采集和vio在线SNR设置模块,支持不同SNR条件下的性能测试。1024QAM调制将10比特映射到复平面上的1024个星座点之一,实现高效数据传输。硬件测试结果表明,在SNR=32dB和40dB时,系统表现出良好的性能。Verilog核心程序展示了各模块的连接与功能实现。
89 7
|
2月前
|
机器学习/深度学习 人工智能 并行计算
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
AI部署架构:A100、H100、A800、H800、H20的差异以及如何选型?开发、测试、生产环境如何进行AI大模型部署架构?
|
2月前
|
人工智能 自然语言处理 JavaScript
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
Magnitude是一个基于视觉AI代理的开源端到端测试框架,通过自然语言构建测试用例,结合推理代理和视觉代理实现智能化的Web应用测试,支持本地运行和CI/CD集成。
314 15
测试工程师要失业?Magnitude:开源AI Agent驱动的端到端测试框架,让Web测试更智能,自动完善测试用例!
|
6天前
|
JavaScript 测试技术 Python
UI自动化测试中的元素等待机制解析
在UI自动化测试中,元素定位失败常因页面存在iframe或缺乏合理等待机制。本文解析三种等待策略及其应用场景:显式等待可精确控制单个元素等待条件,支持自定义轮询;隐式等待全局生效,适合简单页面加载;强制等待仅用于临时调试,正式脚本慎用。通过对比三者执行精度、资源消耗及适用场景,帮助选择最优策略,提升测试效率与稳定性。
|
7天前
|
测试技术 Python
Python接口自动化测试中Mock服务的实施。
总结一下,Mock服务在接口自动化测试中的应用,可以让我们拥有更高的灵活度。而Python的 `unittest.mock`库为我们提供强大的支持。只要我们正确使用Mock服务,那么在任何情况下,无论是接口是否可用,都可以进行准确有效的测试。这样,就大大提高了自动化测试的稳定性和可靠性。
21 0
|
2月前
|
jenkins 测试技术 Shell
利用Apipost轻松实现用户充值系统的API自动化测试
API在现代软件开发中扮演着连接不同系统与模块的关键角色,其测试的重要性日益凸显。传统API测试面临效率低、覆盖率不足及难以融入自动化工作流等问题。Apipost提供了一站式API自动化测试解决方案,支持零代码拖拽编排、全场景覆盖,并可无缝集成CI/CD流程。通过可视化界面,研发与测试人员可基于同一数据源协作,大幅提升效率。同时,Apipost支持动态数据提取、性能压测等功能,满足复杂测试需求。文档还以用户充值系统为例,详细介绍了从创建测试用例到生成报告的全流程,帮助用户快速上手并提升测试质量。
|
4月前
|
人工智能 自然语言处理 测试技术
Potpie.ai:比Copilot更狠!这个AI直接接管项目代码,自动Debug+测试+开发全搞定
Potpie.ai 是一个基于 AI 技术的开源平台,能够为代码库创建定制化的工程代理,自动化代码分析、测试和开发任务。
357 19
Potpie.ai:比Copilot更狠!这个AI直接接管项目代码,自动Debug+测试+开发全搞定
|
4月前
|
存储 人工智能 编译器
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
127 10
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
3月前
|
数据采集 算法 数据安全/隐私保护
【硬件测试】基于FPGA的4ASK调制解调通信系统开发与硬件片内测试,包含信道模块,误码统计模块,可设置SNR
本文介绍了基于FPGA的4ASK调制解调系统的硬件测试版本,该系统包括testbench、高斯信道模块和误码率统计模块,并新增了ILA在线数据采集和VIO在线SNR设置功能。通过VIO设置不同SNR(如15dB和25dB),实现了对系统性能的实时监测与调整。4ASK是一种通过改变载波幅度表示数据的数字调制方式,适用于多种通信场景。FPGA平台的高效性和灵活性使其成为构建高性能通信系统的理想选择。
104 17
|
4月前
|
JSON 前端开发 测试技术
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
168 10
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡