中国球员赵柏清加盟日本联赛,首钢曾有意引进,赵柏清,同曦队,范子铭
2026-07-16

C/C++ 开发效率一直被业内开发人员诟病,单元测试开发效率也是如此,以至于开发人员不愿花时间来写单元测试。那么我们是不是可以通过改善编写单元测试的效率来提升项目的测试用例覆盖率?
本文主要介绍如何利用GCC插件来实现提升C/C++开发者的单元效率工具解决方案,希望对大家在提升单元测试效率上有所启发。
上图展示了C/C++单元测试的基本流程,在日常开发过程中写单元测试是一项比较大工程量的事情,C/C++ 目前单元测试代码都需要自己手动写,而且对于一些私有方法打桩就更加麻烦。
目前业内无开源的自动化测试框架或者工具,倒是有一些商业的自动测试工具,下图展示了我们自动化测试工具及单元测试库:
即使开源界有gtest等测试库的支持,我们仍然需要编写大量的单元测试用例代码浦项制铁技术分析。对于一些private、protected的类方法,编写单元测试用例的效率就更低,需要手动打桩(mock)。同时我们分析测试用例发现,存在很多边界的用例,它们基本上都是很固定或者有一定模式,比如int 最大最小值等。南特比赛预测
如何改善编写单元测试的效率,提升C/C++同学开发效率以及程序质量?我们可以通过提取源文件中的函数、类等信息,然后生成对应的单元测试用例。自动生成用例时需要依赖函数的声明、类的声明等信息,那么我们应该如何获取这些信息呢?
例如:如下的函数定义:
void test(int arg) {}
我们希望能够从上面的函数定义中得到函数的返回值类型、函数名称、函数参数类型、函数作用域。通常我们可以通过以下几种方式得到:
无奈C/C++ 格式比较复杂能够虽然能够使用多种组合来获取对应的函数声明等信息:
void test(int arg){}
void test1(template<template<string>> arg,...){}
void test2(int(*func)(int ,float,...),template<template<string>> arg2){}
那么就需要写一系列的正则表达式:
提取函数名称、参数名:[z-aA-Z_][0-9]+提取函数返回值:^[a-zA-Z_]
关键词提取出来了,但是他有一个很大的问题:怎么判断文件中书写的代码是符合C/C++语法描述呢?
这当然是一种很好的方式,但是工作量巨大,相当于实现一个具备词法、语法分析器简易版本的编译器,而且要适配不同的语法格式,虽然bison可以解决上述的如何判断语法是否正确问题,但是仍然很复杂。
通常我们了解到的GCC编译的过程是以下四个阶段:
源文件->预处理->编译->汇编→链接
但实际上GCC为了支持更多的编程语言、不同的CPU架构做了很多的优化,如下图所示:
上图展示了GCC处理源码及其他优化过程,在前端部分生成的Generic 语言是gcc编译过程中为源码生成的一种与源码语言无关的抽象语法表现形式(AST)。既然GCC编译过程中生成了AST树,那么我们可以通过GCC插件来提取GCC 前端生成的抽象语法树关键信息比如函数返回值、函数名称、参数类型等。总体难度也很高,一方面业内可参考资料很少,只能通过分析GCC的源码来分析AST语法树上的各个节点描述。
本文所描述的自动化生成单元测试用例的解决方案(我们称之为TU:Translate Unit,后文统称为TU)就是基于方法3来实现的,下面我们先来看看我们的自动化测试用例解决方案的效果展示。
在该用例中我们不需要修改任何业务代码就能够为业务代码生成边界测试用例,而且函数参数可边界值实现全排列,大大降低用例遗漏风险。大家可能发现这种没有做任何修改生成的用例是没有断言的,虽然没有断言,它仍然能够帮助发现单元是否会存在边界值引起coredump。
那么如果想要给他加上断言、mock函数,是否没有办法呢?通过C++11 [[]] 新的属性语法,只需要在方法声明或者定义时添加下根据TU的格式添加断言即可,对业务逻辑无侵入。
很多情况下默认生成的边界测试用例还不能覆盖到核心逻辑,所以我们也提供tu::case 来给用户自定义自己的测试用例及断言。比如有一个int foo (int x,long y) 方法,现在想新增一个测试用例返回值123,函数实参1,1000,那么只要在函数声明前加入,以下代码即可:
[[tu::case("NE","123","1","1000")]]
开发过程中我们也常需要对某个方法进行mock(即对原有方法设置一个临时代替方法并且调用方式保持一致),比如某个函数访问Redis、DB这种情况下进行单元测试往往需要对这些方法进行mock,方便其他函数调用进行单元测试,为了方便进行单元测试我们往往会对其进行mock,所以为了方便开发人员进行快速的mock,所以我们提供了tu::mock 的注解帮助开发同学快速的定义注解,然后TU会自动生成对应的mock函数。例如:现在给foo_read 方法mock一个函数,让mock的函数返回10:
GENERIC、GIMPLE和RTL三者构成了gcc中间语言的全部,它们以GIMPLE为核心,由GENERIC承上,由RTL启下,在源文件和目标指令之间的鸿沟之上构建了一个三层的过渡。
GCC在语法分析过程中,所有识别出来的语言部件都用一个叫TREE的变量保存着。这个TREE就是GCC语法树(AST),这个过程叫做GENERIC。实际上它也是GCC的符号表,因为变量名、类型等等这些信息都由TREE关联起来。
下面我们通过gcc编译选项来看下gcc的ast表现形式:
GCC 可以通过添加编译选项-fdump-tree-all 来生成ast 树,ast树文件内容如下:
AST 各个类型描述可以参考:gcc.gnu.org/onlinedocs/…
虽然上图中简单看下一下可以发现,gcc这种表现形式节点与节点之间还存在依赖,比较难于理解,没有clang生成的直观更容易阅读。虽然不利于阅读,但是不影响通过编码来提取AST信息。
如上图所示,我们通过使用不同的插件收集被测试源文件的AST信息、头文件信息、函数注解(属性),将这些重要信息保存起来。
GCC将用户注册插件事件保存到数组中:
然后在编译构建过程中到就会去查找对应的事件有没有设置回调方法如果设置则进行调用,TU主要使用以下几种插件:
PLUGIN_INCLUDE_FILE 用于获取当前文件的所包含的头文件PLUGIN_OVERRIDE_GATE 用户获取普通函数、类PLUGIN_PRE_GENERICIZE 用于获取模板函数的具现化PLUGIN_ATTRIBUTES 用于实现自定义属性或者注解(tu::case u::mock ....)
GCC 支持的所有插件类型如下图所示:(摘自gcc 6.3.0 源码)
如果仅仅只是做边界测试那么仅需要修改构建的脚本比如cmake 添加对应的插件参数即可。
接入简单、边界单元测试可以做到业务代码0修改函数参数可边界值实现全排列,大大降低用例遗漏风险、减少大量重复性的工作快速生成用户自定义用例、mock方法等
1、文章中对比了三种方法自动生成测试用例的方法,下面对这几种方法进行对比:
2、文章中还主要介绍了TU的功能特点以及基于GCC-AST的实现自动生成测试用例的解决方案。
TU解决方案目前在构建时能够自动生成测试用例已经极大降低了单元测试门槛提升单元测试覆盖率,未来我们也希望能够把TU与IDE相结合,探索更高效便捷的使用方式,通过更加便捷的方式生成指定方法的测试用例。比如通过在函数、方法上,通过快捷键生成当前方法的测试用例等。
到此这篇关于C/C++ 单元自动化测试解决方案总结的文章就介绍到这了,更多相关 C++ 单元测试内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
U17世界杯:中国女篮大胜德国+两场狂胜54分 孙晗昀26+8李沅珊23分
U17世界杯:中国女篮大胜德国+两场狂胜54分 孙晗昀26+8李沅珊23分,李沅珊,孙晗昀,中国女篮,女篮世界杯
2026-07-16
王岚嵚转会陷入三方博弈,两大备选已确定,兴奋剂事件能否给山东男篮经济补偿?陈培东续约稳定基本盘,张新宇南下加盟广州
王岚嵚转会陷入三方博弈,两大备选已确定,兴奋剂事件能否给山东男篮经济补偿?陈培东续约稳定基本盘,张新宇南下加盟广州,广州,同曦,王岚嵚,陈培东,山东男篮,天津男篮,王岚(1972年)
2026-07-16
宏远速递!徐杰将获顶薪续约资格,徐昕回归新进展,广东四旧将再就业
宏远速递!徐杰将获顶薪续约资格,徐昕回归新进展,广东四旧将再就业,宏远,同曦,黄荣奇,曾繁日,广东省,本土球员,徐昕(法学家),徐杰(篮球运动员)
2026-07-16
曝浙江北控完成交易!昔日国字号前锋换队,CBA又有一支争冠球队
曝浙江北控完成交易!昔日国字号前锋换队,CBA又有一支争冠球队,cba,孟子凯,浙江男篮,天津男篮,深圳男篮,北京北控队
2026-07-16
150万顶薪逼走赵柏清,欠薪球队持状元签,大学生球员被CBA坑麻了
150万顶薪逼走赵柏清,欠薪球队持状元签,大学生球员被CBA坑麻了,同曦,篮协,cba,赵柏清,状元签,本土球员
2026-07-16
06月28日 世界杯L组第3轮 克罗地亚bs加纳 全场录像回放
06月27日 中超第16轮 重庆铜梁龙vs天津津门虎 全场录像回放
06月27日 中超第16轮 河南队vs上海海港 全场录像回放
06月27日 中超第16轮 深圳新鹏城vs成都蓉城 全场录像回放
06月27日 世界杯小组赛G组第3轮 新西兰vs比利时 全场录像回放
06月27日 世界杯小组赛G组第3轮 埃及vs伊朗 全场录像回放
06月27日 世界杯小组赛H组第3轮 佛得角vs沙特阿拉伯 全场录像回放
06月27日 世界杯小组赛H组第3轮 乌拉圭vs西班牙 全场录像回放
06月27日 世界杯小组赛I组第3轮 塞内加尔vs伊拉克 全场录像回放
06月26日 世界杯小组赛D组第3轮 巴拉圭vs澳大利亚 全场录像回放