C单元测试框架——CMockery (3)中文手册

2023-11-03

Cmockery 单元测试框架

翻译的匆忙,没有校验,纰漏之处感谢请指正。转载请注明来自:see-see ,版权归原文 所有。

Cmockery 是一个轻量级的库,作者用它来做C单元测试。

动机

如今已经有很多的C单元测试框架可用,但大多数框架相当复杂,并且对最新的编译器技术有所依赖。有些开发会使用老版本的编译器, 这样就很难使用那些测试框架。另外,许多测试框架会假设待测代码(程序或模块)执行的平台是同一个。正因为这种假设,很多测试框架需要在待测模块中引入C标准库的头文件,这不符合惯例,或者在待测模块中实现一个不完全的C库。

Cmockery 只需要测试程序与标准C库链接,这能最大限度地减少与标准库头文件的冲突。此外, Cmockery尽量避免使用编译器中比较新的一些特性。

因此,Cmockery就成了一个可用于测试各种不同的代码轻量级的库。如果开发者只是想简单地测试一个程序,并且可以使用最新的编译器,其他单元测试框架也是可取的。

概述

Cmockery 的测试与Cmockery库,标准C库,待测模块链接在一起,最总被编译成一个可以独立运行的程序。在测试过程中,待测模块的任何外部信息都应被模拟,即用测试用例中定义的函数返回值来替换。即使会出现待测代码在实际运行环境和测试环境运行时有差异,仍可视为有效。因为它的目的在于代码模块在功能面上的逻辑测试,不必要求所有的行为都和目标环境一致。

如果不做一些修改,无法将一个模块编译成可执行程序。因此 UNIT_TESTING 预定义应当定义在执行Cmockery单元测试的应用程序中, 编译待测代码时,可用条件编译决定是否参与单元测试。

执行测试

Cmockery单元测试用例就是函数,签名为void function(void **state) . Cmockery 测试程序将(多个)测试用例的函数指针初始化到一个表中,使用unit_test*() 宏. 这个表会传给 run_tests() 宏来执行测试用例。 run_tests() 将适当的异常/信号句柄,以及其他数据结构的指针装入到测试函数。当单元测试结束时, run_tests() 会显示出各种定义的测试是否成功。

run_tests()的使用方法

run_tests.c ------------------------------------------------------------------------------- 

 

 

 

异常处理

在测试函数被run_tests() 执行之前,断言/信号句柄会被一个句柄重载,它可以在异常发生时,显示错误并退出测试函数。 如果一个异常发生在测试函数的外部,例如Cmockery本身,程序将终止执行并返回错误码。

出错处理

当测试函数执行run_tests() 时,如果错误出现了,当前的测试函数将中断,测试程序继续执行下一测试函数。测试失败的通过CMockery函数fail() 给出最终的标志。导致Cmockery库测试失败的事件如下:

 

断言

运行时的断言宏和C标准库的assert() 相似,需要在待测模块中使用Cmockery的mock_assert() 函数重定义。 通常mock_assert() 表示 测试的失败 . 如果一个函数被expect_assert_failure() 宏调用, 那么在这个函数中就要调用mock_assert() ,测试将进行。若没有调用mock_assert() ,表示次函数测试失败。

mock_assert()的使用

assert_module.c -------------------------------------------------------------------------------

 

 

 

 

assert_module_test.c -------------------------------------------------------------------------------

 

 

 

断言宏

Cmockery提供了一系列的断言宏,在测试程序的使用方法和C标准中的用法一致。 当断言错误发生时,Cmockery的断言宏会将这个这个错误输出到标准错误流,并把这个测试标记为失败。 由于标准C库中assert()的是限制,Cmockery的assert_true() 和 assert_false() 宏只能显示导致断言失败的表达式。Cmockery中和具体类型相关的断言宏, assert_{类型}_equal() and assert_{类型}_not_equal(), 显示那些导致断言失败的数据, 这样可以增加数据的可视化,辅助调试那些出错的测试用例。

assert_{类型}_equal()宏的使用

assert_macro.c -------------------------------------------------------------------------------

 

 

 

 

assert_macro_test.c ----------------------------------------------------------------------------

 

 

 

 

动态内存分配

为了能用Cmockery测试待测模块中的内存泄漏,缓存溢出和underflows问题,应该将对malloc()calloc()free() 的调用分别替换成test_malloc()test_calloc()test_free() 。每次释放块内存是使用test_free() ,如果一个内存块被 标记为测试失败 ,它将检测内存崩溃。所有块的内存分配使用 test_*() 函数,Cmockery库将跟踪它们。当测试完成时,如果有任何分配的块没有被释放(内存泄漏), 这些信息会被记录,此测试标记为失败。

为了简单起见,Cmockery会在同一进程中执行所有的测试。因此,一个测试程序的所有测试用例,共用一个单独的地址空间, 也就是说,一个测试用例的内存崩溃,会导致整个测试程序的提前结束。

Cmockery的分配器的使用

allocate_module.c -------------------------------------------------------------------------------

 

 

 

 

allocate_module_test.c -------------------------------------------------------------------------------

 

 

 

 

模拟的函数

一个单元测试最好能将待测函数或模块从外部依赖中隔离。 这就会用到模拟函数,它通过动态或静态方式链接到待测模块中去。 当被测代码直接引用外部函数是,模拟函数必须静态链接。 动态链接是一个简单的过程,将一个函数指针放到一个表中,给待测模块中一个测试用例定义的模拟函数引用。

(模拟函数)返回值

为了简化模拟函数的实现,Cmockery 提供了给模拟函数的每个测试用例存放返回值的功能,使用的是 will_return() 函数。然后,这些值将通过每个模拟函数调用mock() 返回。 传给will_return() 的值,将分别添加到每个函数所特有的队列中去。连续调用 mock() ,将从函数的队列中移除一个返回值。 这使一个模拟函数通过多次调用mock() ,来返回(多个)输出参数和(一个)返回值成为可能。 此外,一个模拟函数多次调用(多个)返回值的做法也是可以的。

will_return()的使用

database.h -------------------------------------------------------------------------------

 

 

customer_database.c -------------------------------------------------------------------------------

 

 

 

customer_database_test.c -------------------------------------------------------------------------------

 

 

 

参数检测

除了存储模拟函数的返回值之外,Cmockery还提供了对模拟函数参数期望值的存储功能,使用的是 expect_*()函数,一个模拟函数的参数可以通过check_expected()宏来做有效的验证.

连续调用expect_*()宏,是用队列中的一个参数值来检测给定的参数。 check_expected()检测一个的函数参数,它与expect_*()相对应,即将出队的值。 如果参数检验失败,这个测试将标记为失败。 此外,如果调用check_expected()时,队列中没有参数值出队,测试也会失败。

expect_*()的使用

product_database.c -------------------------------------------------------------------------------

 

 

 

product_database_test.c -------------------------------------------------------------------------------

 

 

 

测试状态

Cmockery允许每个测试用例多次装载和卸载函数的做法, 装载函数,通过unit_test_setup()unit_test_setup_teardown() 宏给出, 支持多个测试用例公共的通用初始化; 此外,卸载函数,通过unit_test_teardown()unit_test_setup_teardown() 宏,给出一个测试用例在执行失败情况下的代码路径。

unit_test_setup_teardown()的使用

key_value.c -------------------------------------------------------------------------------

 

 

 

 

key_value_test.c -------------------------------------------------------------------------------

 

 

 

实例

一个很小基于命令行的计算器程序calculator.c
与计算器程序的测试程序calculator_test.c ,它包含了本文所涉及的所有特性的一个实例。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C单元测试框架——CMockery (3)中文手册 的相关文章

  • C++ 维护子类对象的混合集合

    如果我在这里错过了一个相当基本的概念 我很抱歉 但我正在尝试弄清楚如何维护多个类类型的集合 所有类类型都派生自同一个父类 并且在检索它们时仍然可以访问它们的特定于子类的方法从集合中 作为上下文 我有一个基类 BaseClass 和许多类 例
  • 使用 lambda 表达式注册类型

    我想知道如何在 UnityContainer 中实现这样的功能 container RegisterType
  • 如何在多线程C++ 17程序中交换两个指针?

    我有两个指针 pA 和 pB 它们指向两个大的哈希映射对象 当pB指向的哈希图完全更新后 我想交换pB和pA 在C 17中 如何快速且线程安全地交换它们 原子 我是 c 17 的新手 2个指针的原子无等待交换可以通过以下方式实现 inclu
  • 以编程方式读取 SQL Server 查询计划建议的 SQL 特定执行的索引?

    如果我在 SSMS 中运行此命令 set showplan xml on GO exec some procedure arg1 arg2 arg3 GO set showplan xml off GO 我获得查询执行中涉及的完整调用堆栈的
  • 在c#中执行Redis控制台命令

    我需要从 Redis 控制台获取 客户端列表 输出以在我的 C 应用程序中使用 有没有办法使用 ConnectionMultiplexer 执行该命令 或者是否有内置方法可以查找该信息 CLIENT LIST是 服务器 命令 而不是 数据库
  • C++ 是否可以在 MacOS 上与 OpenMP 和 boost 兼容?

    我现在已经尝试了很多事情并得出了一些结论 也许 我监督了一些事情 但似乎我无法完成我想要的事情 问题是 是否有可能使用 OpenMP 和 boost 在 MacOS High Sierra 上编译 C 一些发现 如果我错了请纠正我 Open
  • 函数参数的默认参数是否被视为该参数的初始值设定项?

    假设我有这样的函数声明 static const int R 0 static const int I 0 void f const int r R void g int i I 根据 dcl fct default 1 如果在参数声明中指
  • 为什么在 WebApi 上下文中在 using 块中使用 HttpClient 是错误的?

    那么 问题是为什么在 using 块中使用 HttpClient 是错误的 但在 WebApi 上下文中呢 我一直在读这篇文章不要阻止异步代码 https blog stephencleary com 2012 07 dont block
  • 从同一个类中的另一个构造函数调用构造函数

    我有一个带有两个构造函数的类 C 这是代码片段 public class FooBar public FooBar string s constructor 1 some functionality public FooBar int i
  • Python 属性和 Swig

    我正在尝试使用 swig 为一些 C 代码创建 python 绑定 我似乎遇到了一个问题 试图从我拥有的一些访问器函数创建 python 属性 方法如下 class Player public void entity Entity enti
  • 打破 ReadFile() 阻塞 - 命名管道 (Windows API)

    为了简化 这是一种命名管道服务器正在等待命名管道客户端写入管道的情况 使用 WriteFile 阻塞的 Windows API 是 ReadFile 服务器已创建启用阻塞的同步管道 无重叠 I O 客户端已连接 现在服务器正在等待一些数据
  • 使用valgrind进行GDB远程调试

    如果我使用远程调试gdb我连接到gdbserver using target remote host 2345 如果我使用 valgrind 和 gdb 调试内存错误 以中断无效内存访问 我会使用 target remote vgdb 启动
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • 如何在 C 中安全地声明 16 位字符串文字?

    我知道已经有一个标准方法 前缀为L wchar t test literal L Test 问题是wchar t不保证是16位 但是对于我的项目 我需要16位wchar t 我还想避免通过的要求 fshort wchar 那么 C 不是 C
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • Unity:通过拦截将两个接口注册为一个单例

    我有一个实现两个接口的类 我想对该类的方法应用拦截 我正在遵循中的建议Unity 将两个接口注册为一个单例 https stackoverflow com questions 1394650 unity register two inter
  • 如何在richtextbox中使用多颜色[重复]

    这个问题在这里已经有答案了 我使用 C windows 窗体 并且有 richtextbox 我想将一些文本设置为红色 一些设置为绿色 一些设置为黑色 怎么办呢 附图片 System Windows Forms RichTextBox有一个
  • 为boost python编译的.so找不到模块

    我正在尝试将 C 代码包装到 python 中 只需一个类即可导出两个函数 我编译为map so 当我尝试时import map得到像噪音一样的错误 Traceback most recent call last File
  • 灵气序列解析问题

    我在使用 Spirit Qi 2 4 编写解析器时遇到一些问题 我有一系列键值对以以下格式解析

随机推荐

  • 开源OCR引擎Tesseract-OCR

    Overview Tesseract的OCR引擎最先由HP实验室于1985年开始研发 至1995年时已经成为OCR业内最准确的三款识别引擎之一 然而 HP不久便决定放弃OCR业务 Tesseract也从此尘封 数年以后 HP意识到 与其将
  • VSCode 必装的 10 个高效开发插件

    本文介绍了目前前端开发最受欢迎的开发工具 VSCode 必装的 10 个开发插件 用于大大提高软件开发的效率 VSCode 的基本使用可以参考我的原创视频教程 VSCode 高效开发必装插件 VSCode Visual Studio Cod
  • jquery val() 获取不到值的问题排查

    表单校验用jquery validation 实现 基本功能很快实现 在测试时发现自定义的一个比较开始结束日期的校验不起作用 var begin param val var reg new RegExp g begin begin repl
  • arcgis 9.3 sde 安装 启动服务问题

    1 arcgis 9 3 注册 服务 命令 sdeservice o create d oracle orcl p sde i esri sde 2 启动 sde 服务 报错 3 以上1命令在机器上执行不认 用以下命令 sdeservice
  • 【DevOps-监控】生产环境是如何落地一套全方位的监控系统

    生产环境监控究竟需什么样的功能 我们试想一下 如果部署一个监控系统到生产环境 需要满足哪些功能呢 既然是监控 肯定需要监控我们的主机资源信息包括cpu 内存 网络 磁盘等信息吧 其次还得监控容器的相关资源信息 然后我们可能还需要历史数据 几
  • uni-app vuex全局计时

    功能需求 在A页面进入时候开始计时中间会去到B页面查看数据 但是并没有销毁当前页面 所以计时一直在 直到在B页面提交数据 才结束计时 在根文件夹创建 store文件夹 同时创建index js文件 import Vue from vue i
  • TensorFlow:实战Google深度学习框架(二)实现简单神经网络

    3 4 TensorFlow实现神经网络 3 4 1 TensorFlow游乐场 3 4 2 前向传播 3 4 3 神经网络参数与TensorFlow变量 变量和张量的关系 变量的三个属性 张量 维度 类型 3 4 4通过TensorFlo
  • flask-sqlalchemy插件使用

    1 Flask SQLAlchemy插件的使用 该插件对SQLAlchemy进行了简单的封装 使得我们可以更加简单的使用 初始化数据库 无需导入create engine from flask import Flask from flask
  • win10怎么设置WiFi与有线优先级

    原文 https blog csdn net u010921682 article details 88964982 经过测试 文章中第二种方式有效 不过我的优先级与原文中的不同 我是wifi优先于有线 如下 二 修改 接口跃点数 这个名词
  • Android的中http协议HttpURLConnection中post请求

    public class MainActivity extends AppCompatActivity private TextView textView Override protected void onCreate Bundle sa
  • Idea里面关于时间date报错Unhandled exception: java.text.ParseException的解决方案

    我一直报这个错找不到 结果是因为我导包的原因 idea自动导包导出来是这个 但是咱们需要的是这个 就不报错了
  • Lerna包管理

    认识lerna 导读 本章节主要讲解Lerna是什么 Lerna有什么用 如何使用Lerna进行npm包管理 大厂的Lerna版本管理策略是怎么做的 Lerna是如何实现本地包依赖管理以及底层原理是什么 读者可以带着这些问题去阅读 使学习事
  • 利用jni将Eclipse与C++、Opencv无缝连接

    利用jni将Eclipse与C Opencv无缝连接 博主 w风的季节 日期 2018 4 11 现在越来越多的大学生实验室或者创新项目需要用到将JAVA与C 之间的混合编程 因此本篇就来讲解一下Eclipse中用java写的APP如何将C
  • Spring Boot favicon.ico自定义设置

    做网页的都知道 网页打开后几乎都会有一个favicn的小图标 但是在spring boot中如何设置呢 下面告诉大家一个自定制的方法 非常简单 1 在配置application properties中加入 spring mvc favico
  • 信息熵,信息增益

    信息熵 信息增益 概要 实例一 实例二 概要 信息增益表示得知特征A的信息而使得类Z的信息的不确定性减少的程度 特征A对数据集D的信息增益 G D A 定义为集合的信息熵 H D 与特征A给定条件下D的信息条件熵 H D A 之差 即公式为
  • 机器学习入门-提取文章的主题词 1.jieba.analyse.extract_tags(提取主题词)

    1 jieba analyse extract tags text text必须是一连串的字符串才可以 第一步 进行语料库的读取 第二步 进行分词操作 第三步 载入停用词 同时对分词后的语料库进行停用词的去除 第四步 选取一段文本分词列表
  • 关于ASP.NET邮件发送的学习心得

    ASP net邮件发送是一种非常常见的功能 它可以让我们在网站中实现发送邮件的功能 比如用户注册成功后发送欢迎邮件 或者是找回密码时发送重置密码邮件等等 在学习ASP net邮件发送的过程中 我总结了以下几点心得 一 SMTP服务器的配置
  • 【解决问题】Transaction was marked for rollback only; cannot commit

    问题现象 导入文件的时候直接报错 Transaction was marked for rollback only cannot commit nested exception is org hibernate TransactionExc
  • JavaScript运算符详解

    JavaScript运算符详解 目录 JavaScript运算符详解 1 算术运算符 1 1 加法运算符 1 1 1 基本运算规则 1 1 2 对象的相加 1 2 余数运算符 1 3 自增和自减运算符 1 4 正负数值运算符 1 5 指数运
  • C单元测试框架——CMockery (3)中文手册

    Cmockery 单元测试框架 翻译的匆忙 没有校验 纰漏之处感谢请指正 转载请注明来自 see see 版权归原文 所有 Cmockery 是一个轻量级的库 作者用它来做C单元测试 目录 动机 概述 执行测试 异常处理 出错处理 断言 断