GoogleTest单元测试学习
一、GTest简介
GoogleTest是一个单元测试的框架。
单元测试:
单元测试在函数在整个工程运行起来之前,对该函数进行测试,来判断当前函数能否达到预期的效果。
使用GoogleTest:
1.将GoogleTest编译为库;
2.在代码中链接这个库。
二、GTest编译安装
1.源代码编译:
#下载gtest,release-1.8.0
git clone https://github.com/google/googletest
# gtest编译
cd googletest
#生成Makefile文件(先安装cmake,brew install cmake),继续输入命令编译:
cmake CMakeLists.txt
#执行make,生成两个静态库:libgtest.a libgtest_main.a
make
#拷贝到系统目录,注意,如果下诉目录位置在不同版本位置有变动,用find . -name "libgtest*.a" 找到位置
sudo cp libgtest*.a /usr/lib
sudo cp –a include/gtest/ /usr/include
2.检查是否安装成功
可以写一个简单的测试代码gtest.cpp,如下:
#include<gtest/gtest.h>
int add(int a,int b){return a+b;
}
TEST(testCase,test0){EXPECT_EQ(add(2,3),5);
}
int main(int argc,char **argv){testing::InitGoogleTest(&argc,argv);return RUN_ALL_TESTS();
}
在终端中编译该文件,并运行:
g++ -std=c++11 gtest.cpp -lgtest -lpthread -o gtest.out
./gtest.out
三、GTest使用
单元测试(Unit Test)是对软件基本组成单元(如函数或是一个类的方法)进行的测试,是开发者编写的一小段代码,用于检验被测试代码一个很小的、很明确的功能是否正确。
在gtest中,一个测试用例(test case)可以包含一个或多个测试。一个测试程序可以包含多个测试用例。
可以通过操作符”<<”将一些自定义的信息输出,如:
ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";for (int i = 0; i < x.size(); ++i) {EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
}
1.定义测试函数
应用 googletest 编写单元测试时,使用 TEST() 宏来声明测试函数:
TEST(GlobalConfigurationTest, configurationDataTest)
2.断言/宏测试
gtest中,断言是用以检查条件是否为真。
ASSERT_* 版本的断言失败时会产生致命失败,并结束当前函数;
EXPECT_* 版本的断言失败时产生非致命失败,但不会中止当前函数。
3.事件机制
全局事件
要实现全局事件,必须写一个类,继承testing::Environment类,实现里面的SetUp和TearDown方法。
SetUp()方法在所有案例执行前执行
TearDown()方法在所有案例执行后执行
还需要告诉gtest添加这个全局事件,我们需要在main函数中通过testing::AddGlobalTestEnvironment方法将事件挂进来,也就是说,我们可以写很多个这样的类,然后将他们的事件都挂上去。
TestSuite事件
我们需要写一个类,继承testing::Test,然后实现两个静态方法
SetUpTestCase() 方法在第一个TestCase之前执行
TearDownTestCase() 方法在最后一个TestCase之后执行
在编写测试案例时,我们需要使用TEST_F这个宏,第一个参数必须是我们上面类的名字,代表一个TestSuite。
TestCase事件
TestCase事件是挂在每个案例执行前后的,实现方式和上面的几乎一样,不过需要实现的是SetUp方法和TearDown方法:
SetUp()方法在每个TestCase之前执行
TearDown()方法在每个TestCase之后执行
四、例程
1.一个超简单的 googletest 单元测试实例
#include<gtest/gtest.h>
int add(int a,int b){return a+b;
}
TEST(testCase,test0){EXPECT_EQ(add(2,3),5);
}
int main(int argc,char **argv){testing::InitGoogleTest(&argc,argv);return RUN_ALL_TESTS();
}
2.一个较完整的 googletest 单元测试实例
// Configure.h #pragma once
#include <string> #include <vector>
class Configure { private: std::vector<std::string> vItems;
public: int addItem(std::string str);
std::string getItem(int index);
int getSize(); };
// Configure.cpp #include "Configure.h"
#include <algorithm>
/** * @brief Add an item to configuration store. Duplicate item will be ignored * @param str item to be stored * @return the index of added configuration item */ int Configure::addItem(std::string str) {
std::vector<std::string>::const_iterator vi=std::find(vItems.begin(), vItems.end(), str); if (vi != vItems.end()) return vi - vItems.begin();
vItems.push_back(str); return vItems.size() - 1; }
/** * @brief Return the configure item at specified index. * If the index is out of range, "" will be returned * @param index the index of item * @return the item at specified index */ std::string Configure::getItem(int index) { if (index >= vItems.size()) return ""; else return vItems.at(index); }
/// Retrieve the information about how many configuration items we have had int Configure::getSize() { return vItems.size(); }
// ConfigureTest.cpp #include <gtest/gtest.h>
#include "Configure.h"
TEST(ConfigureTest, addItem) { // do some initialization Configure* pc = new Configure(); // validate the pointer is not null ASSERT_TRUE(pc != NULL);
// call the method we want to test pc->addItem("A"); pc->addItem("B"); pc->addItem("A");
// validate the result after operation EXPECT_EQ(pc->getSize(), 2); EXPECT_STREQ(pc->getItem(0).c_str(), "A"); EXPECT_STREQ(pc->getItem(1).c_str(), "B"); EXPECT_STREQ(pc->getItem(10).c_str(), "");
delete pc; }
main()函数:
#include <gtest/gtest.h>
int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv);
// Runs all tests using Google Test. return RUN_ALL_TESTS(); }
最后,将所有测试代码及main.cpp编译并链接到目标程序中。
此外,在运行可执行目标程序时,可以使用 --gtest_filter 来指定要执行的测试用例,如:
./foo_test 没有指定filter,运行所有测试;
./foo_test --gtest_filter=* 指定filter为*,运行所有测试;
./foo_test --gtest_filter=FooTest.* 运行测试用例FooTest的所有测试;
./foo_test --gtest_filter=*Null*:*Constructor* 运行所有全名(即测试用例名 + “ . ” + 测试名,如 GlobalConfigurationTest.noConfigureFileTest)含有"Null"或"Constructor"的测试;
./foo_test --gtest_filter=FooTest.*-FooTest.Bar 运行测试用例FooTest的所有测试,但不包括FooTest.Bar。
五、我自己学习 googletest 单元测试时写的例程:
//
// Created by toson on 19-3-8.
//
#include <gtest/gtest.h>
#include "shtf_sdk_interface.h"//第一个参数是测试用例名,第二个参数是测试名:随后的测试结果将以"测试用例名.测试名"的形式给出
TEST(FaceImageInit_testCase, FaceImageInit_test){//test dataFaceImage* image = new FaceImage;char errorinfo[256];//生成随机数用于测试srand((unsigned)time(NULL));//测试正数image->width = rand();image->height = rand();image->size = rand();image->bgr = (unsigned char*)rand();cout << "image->width :" << image->width << endl;cout << "image->height:" << image->height << endl;cout << "image->size :" << image->size << endl;FaceImageInit(image,errorinfo);//断言是否完成程序该完成的功能EXPECT_EQ(image->width, 0);EXPECT_EQ(image->height, 0);EXPECT_EQ(image->size, 0);EXPECT_EQ(image->bgr, nullptr);//测试负数image->width = -rand();image->height = -rand();image->size = -rand();image->bgr = (unsigned char*)-rand();cout << "image->width :" << image->width << endl;cout << "image->height:" << image->height << endl;cout << "image->size :" << image->size << endl;FaceImageInit(image,errorinfo);EXPECT_EQ(image->width, 0);EXPECT_EQ(image->height, 0);EXPECT_EQ(image->size, 0);EXPECT_EQ(image->bgr, nullptr);delete image;
}int main(int argc,char **argv){testing::InitGoogleTest(&argc,argv); //用来处理Test相关的命令行开关,如果不关注也可不加return RUN_ALL_TESTS();
}/*----------------------------------------------------------*/在测试执行之前,系统会先执行TestEnvironment的SetUp()方法;在所有测试用例执行完之后,系统会执行TestEnvironment的TearDown()方法。另外,我们可以定义任意多个继承自testing::Environment的子类,以实现不同的全局事件。所有的子类的SetUp()按照我们调用testing::AddGlobalTestEnvironment添加它们的先后顺序执行,而TearDown()的执行顺序则与添加顺序相反。
//class ShtfSdkTnterfaceTestEnvironment : public testing::Environment{ //我的全局环境设置
//public:
// virtual void SetUp() //在所有测试启动之前需要做的操作
// {
// ;//std::cout << "Foo FooEnvironment SetUP" << std::endl;
// }
// virtual void TearDown() //在所有测试运行结束后需要做的操作
// {
// ;//std::cout << "Foo FooEnvironment TearDown" << std::endl;
// }TestEnvironment(){ //在SetUp()之前cout<<"TestEnvironment()"<<endl;};~TestEnvironment(){ //在TearDown()之后cout<<"~TestEnvironment()"<<endl;};
//};
//
在测试套件的第一个测试用例开始前,SetUpTestCase()函数会被调用,而在测试套件中的最后一个测试用例运行结束后,TearDownTestCase()函数会被调用。
//class TestMap:public testing::Test //套装例子
//{
//public:
// static void SetUpTestCase() //测试套件的第一个测试用例开始前,SetUpTestCase()函数会被调用
// {
// ;//cout<<"SetUpTestCase()"<<endl;
// s=new Student(23);
// }
// static void TearDownTestCase() //在测试套件中的最后一个测试用例运行结束后,TearDownTestCase()函数会被调用
// {
// delete s;
// ;//cout<<"TearDownTestCase()"<<endl;
// }
// void SetUp() //测试套件的每次测试用例开始前,SetUp()函数会被调用
// {
// ;//cout<<"SetUp(), running"<<endl;
// }
// void TearDown() //测试套件的每次测试用例运行结束后,TearDown()函数会被调用
// {
// ;//cout<<"TearDown(), stopping"<<endl;
// }TestMap(){ //在SetUpTestCase()之后,在SetUp()之前cout<<"TestMap()"<<endl;};~TestMap(){ //在TearDown()之后,在SetUpTestCase()之前cout<<"~TestMap()"<<endl;};
//};
//
第一个参数是测试用例名,第二个参数是测试名:随后的测试结果将以"测试用例名.测试名"的形式给出
//TEST_F(TestMap, Test1) //对TestMap进行测试,test1
//{
// s->print();
// Student s1(18);
// s1.print();ASSERT_EQ(s1, (Student *)NULL);ASSERT_NE(s1, (Student )NULL);
//}
//TEST_F(TestMap, Test2) //对TestMap进行测试,test2
//{Student *s1;
// s->print();ASSERT_NE(Student(23), NULL);ASSERT_NE(s1, (Student *)NULL);
// ASSERT_EQ(0, 0);
//}
//
//int main(int argc, char** argv)
//{
// //在RUN_ALL_TESTS()之前,我们调用如下语句:
// // testing::AddGlobalTestEnvironment(new GlobalEnvent);
// // 将这个测试层面的的事件添加到事件列表即可。
// testing::AddGlobalTestEnvironment(new ShtfSdkTnterfaceTestEnvironment);
// testing::InitGoogleTest(&argc, argv); //用来处理Test相关的命令行开关,如果不关注也可不加
// return RUN_ALL_TESTS();
//}
GoogleTest单元测试学习相关推荐
- Qt程序单元测试学习记录
7月比较忙,很少更新博客,上旬任务是给公司原来的程序做简单的单元测试.毕业这两年写过很多代码,从来没有注意过单元测试这东西,现在开始认真对待,开始看别人写的文章来学习.这里记录下最近学到的,以及自 ...
- C++单元测试学习总结9
C++单元测试一:并非看上去那么简单--几个很实际的问题 理想与现实 为Java和C#做单元测试,基本上都有比较统一的工具.模式可用,IDE的支持也非常到位:可是到 了C++这里,一切就变的那样的&q ...
- 在CodeBlocks下配置GoogleTest单元测试框架
环境准备 Windows 10 Code::Blocks 20.03 Google Test 1.7.0 CMake 3.11.0 编译GoogleTest 一.创建一个工作目录D:\gtest,将刚 ...
- Android 单元测试学习计划
网上查了一下Android单元测试相关的知识点,总结了一个学习步骤: 1. 什么是单元测试 2. 单元测试正反面: 2.1. 重要性 2.2. 缺陷 2.3. 策略 3. 单元测试的基础知识: 3.1 ...
- googletest单元测试框架安装及使用
1.下载googletest 介绍:现在的googletest软件包分两部分,一部分是gtest,单元测试框架,实现对单元测试用例的管理和设计,另一部分是gmock,实现打桩功能,这两个可以结合起来使 ...
- Android单元测试学习总结
文章目录 一.本地单元测试 1. 创建测试类 2. Assert类中的常用断言方法 3. 运行测试类 4. 运行单个测试方法或多个测试类 二.Mockito测试框架的使用 1. Mock概念的理解 2 ...
- Go单元测试学习笔记 V1.0
与你相识 博主介绍: – 本人是普通大学生一枚,每天钻研计算机技能,CSDN主要分享一些技术内容,因我常常去寻找资料,不经常能找到合适的,精品的,全面的内容,导致我花费了大量的时间,所以会将摸索的内容 ...
- Android单元测试学习之 Junit4
保持单元测试的独立性,单元测试用例之间绝不能互相调用,也不能依赖执行的先后次序 Repeatable 重复性 单元测试是可以重复执行的,不能收到外界环境的影响,因为单元测试通常会被放到持续集成中,每次 ...
- Junit单元测试学习笔记一
我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能很强大,但我们在程序中只用到该函数的一小部分功能,并且经过调试可以确定,这一小部分功能是正确的.但是,我们同时应该确保每一个函数 ...
最新文章
- 数字货币 分层确定性钱包(HD Wallets)
- oracle怎么判断是裸设备安装,Oracle 9i下以裸设备方式安装数据库
- vue3中websocket用法
- 文件系统(02):基于SpringBoot框架,管理Xml和CSV文件类型
- linux 3d加速驱动_实时Linux,3D打印自行车,Google的“加速的移动页面”等
- linux 隐藏显示终端光标
- 编程实现 带符号减法溢出判断
- .Net中的加密解密
- Android开发学习——基础学习
- Python内置函数filter(),map(),reduce(),lambda
- 安卓手机实现wifi中继、WiFi信号增强
- 【超图+CESIUM】【基础API使用示例】34、超图|CESIUM - 绘制光流流光线段
- xp计算机共享能否指定用户,XP怎么设置局域网共享?
- canvas实现虚线带箭头效果
- 机器学习笔记之R语言基础5(T,F检验)
- 计算机可以计算出十的一百次方吗,世界上最大的数字单位 古戈尔(1古戈尔等于10的100次方)...
- html style属性的用法
- EFR32--如何在EFR32程序中修改UUID
- 每日格言积累及总结——更新中
- mac 下备份同步qq聊天纪录
热门文章
- 张朝霞博客,先谈下个人的一些事情,总结自己
- win10录屏_一分钟教你学会两种电脑录屏方法,以后别再说不知道了
- 浅析Tomcat结构以及自定义嵌入式Tomcat
- 树莓派gpio接口编程基础知识
- CE修改模拟器里的数据
- 顺无盘linux win10包,(2018.05.21)云更新2016正式版x86_2016.10.15.4976无盘xp-win7x32-x64-win10x64公包...
- AdaBoost人脸检测算法1(转…
- Java中的Comparable接口和Comparator接口
- 测试计划与测试方案包括内容
- 使用node.js http-server启动了,但是网页打开显示无法正常工作