stub工具源码:https://github.com/coolxv/cpp-stub/tree/master/src
这里做下简单的背景介绍,ut的基础介绍:可以先去看下先去的文章:https://blog.csdn.net/anranjingsi/article/details/106084223
前面也使用过gtest+gmock框架给C/C++做单元测试,但gmock的使用有着明显的限制:1)必需是C++的类函数词可以被mock; 2)要求编码时就要考虑那些函数会被mock,将其定义为虚函数;3)需要写mock类,代码量大。
所以对于纯C代码或者非C++类的代码就无法使用gmock来对函数进行mock,这里推荐使用cpp-stub对C语言代码打桩做UT,可以简单有效的解决UT测试的打桩问题。
cpp-stub的原理:
获取被打桩函数和桩函数的函数地址,在调用被打桩函数时,替换成桩函数。
cpp-stub的简单教程:
1)安装:在安装完gtest后,只需要将stub.h放入到include的目录中即可;
2)使用:使用也很简单,首先在测试用例cpp中include "stub.h",然后包含被测试的.c文件,构建测试程序,对需要程序中出现的一些需要返回指定值的被调用函数做桩函数替换即可,可见以下简单例子:
假设testStub工程有个被测试c文件func.c:
#include "func.h"
int check(int a){
return a+50;
}
int fun_greater100(int a){
if(check(a) <= 100){
return 0;
}
return 1;
}
这里我们要测试这个fun_greater100函数,这里我们先对check函数打桩,让check函数返回我们希望它返回的数值,以此来测试fun_greater100函数的逻辑否正确,测试工程的用例代码如下:
测试用例文件test_func.cpp:
#include <gtest\gtest.h>
#include <gtest\stub.h>
#include "..\testStub\func.c"
int check_stub1(int a){//check函数的桩函数,与check函数形式一样
return 50;
}
TEST(TestSuite1, fun_greater100_1){
Stub stub;//实例化对象
stub.set(check, check_stub1);//这里设置桩,将check函数替换为check_stub1
int ret = fun_greater100(101);//执行fun_greater100则会调用设置的桩函数check_stub1
EXPECT_EQ(ret, 0);//返回的结果为0,而不是1
}
这里测试用例必定通过,即使我们设置的参数时101,但fun_greater100函数实际调用的就是check_stub1函数,所以测试用例通过。
这里我们再扩展一下测试用例:
#include <gtest\gtest.h>
#include <gtest\stub.h>
#include "..\testStub\func.c"
int check_stub1(int a){
return 50;
}
int check_stub2(int a){
return 101;
}
TEST(TestSuite1, fun_greater100_1){
Stub stub;
stub.set(check, check_stub1);
int ret = fun_greater100(101);
EXPECT_EQ(ret, 0);
}
TEST(TestSuite1, fun_greater100_2){
Stub stub;
stub.set(check, check_stub2);
int ret = fun_greater100(50);
EXPECT_EQ(ret, 1);
}
执行结果如下:
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from TestSuite1
[ RUN ] TestSuite1.fun_greater100_1
[ OK ] TestSuite1.fun_greater100_1 (0 ms)
[ RUN ] TestSuite1.fun_greater100_2
[ OK ] TestSuite1.fun_greater100_2 (0 ms)
[----------] 2 tests from TestSuite1 (8 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (16 ms total)
[ PASSED ] 2 tests.
在git_hub上提供了很多的测试例子,像是C++的类成员、虚函数、重载函数等等的打桩都有相关的例子,读者可自行学习,都是非常的简单易懂。
cpp-stub的一些问题:
1)不可以对exit函数打桩;
2)不可以对纯虚函数打桩;
3)不可以对static声明的普通内部函数打桩。
后面我还会介绍下emock的使用,它是在mockcpp的基础上做的进一步优化,语法与mockcpp类似,但更加的强大。