gtest 总结

gtest without main

Google的C测试框架有两个输出库:一个是gtest.lib,另一个是gtest_main.lib。

依赖gtest.lib 需要实现自己的入口函数main

int main(int argc, char* argv[])
{testing::AddGlobalTestEnvironment(new FooEnvironment);::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS();  return 0;}

依赖gtest_main.lib 提供了测试应用程序入口点(即主要功能)的默认实现,添加编译依赖-l gtest_main

[Getting started with Google C++ Testing Framework](javascript:void())引用:

“[…] maybe you think that writing
all those main() functions is too much
work? We agree with you completely and
that’s why Google Test provides a
basic implementation of main(). If it
fits your needs, then just link your
test with gtest_main library and you

Gmock

C++ mock一个新类继承抽象类

使用MOCK_METHODx宏声明的类成员函数;详见 MOCK_METHOD*系列宏,参考如下博客

https://blog.csdn.net/songqier/article/details/79188237

使用EXPECT_CALL等一系列宏来指定这些函数在被调用时的动作。

在此基础上期望待测函数的输出

C mock 三种方式

方法一:利用C语言的预处理(在编译之前进行Mock)

#ifdef TESTING#define depend_func(account_no,item)\ function body\/* extend as function body during compile procedure, while the function name. so will not find the depend_func symble in ld process */#endif

方法二: 使用函数指针(编译期进行mock)

#ifdef TESTINGdepend_func= depend_func_mock
#elsedepend_func= depend_func_real
#endif

方法三: 在编译之后 Link时候进行替换

编写包括depend_func的库函数,在link的时候使用这个假的库函数

linux_gtest

linux下gtest的使用

环境配置(ubuntu 14.04 32bit)

直接去官方网站下载,可以下载最新的release版本
https://github.com/google/googletest

$ ./travis.sh$ cmake ./CMakeLists.txt$ make $ sudo make install### makefile.PHONY: all cleanCC=g++
OBJ_DIR=./obj
HEADERS=-I.
DEBUG=-g -ggdb
WALL=-Wall -W
CFLAGS=$(WALL) $(DEBUG)
L_CC=$(CC) $(CFLAGS) $(HEADERS)C_SRC=${wildcard *.cpp}
C_OBJ=$(patsubst %.cpp, $(OBJ_DIR)/%.o, $(C_SRC)) #目标文件
C_EXE=a.outall:prepare $(C_EXE)prepare:@if [ ! -d $(OBJ_DIR)  ];then mkdir $(OBJ_DIR); fi$(C_EXE):$(C_OBJ)$(L_CC) $^ -o $@ -lgtest -lgtest_main -lpthread$(OBJ_DIR)/%.o:%.cpp$(L_CC) -c $< -o $@clean:@-rm -f $(C_EXE)@-rm -rf $(OBJ_DIR)

参数化

在测试时,经常需要考虑被测函数传入不同参数的值的情况。当然可以写很多的Assert或 EXPECT断言,但是是不是太多了,要写多少重复的的东西

比如

TEST(IsPrimeTest, HandleTrueReturn)
{EXPECT_TRUE(IsPrime(3));EXPECT_TRUE(IsPrime(5));EXPECT_TRUE(IsPrime(11));EXPECT_TRUE(IsPrime(23));EXPECT_TRUE(IsPrime(17));
}

参数化,采用一个较为通用的方法,你要测多少数据,自己加上就行了,不需要copy那么多一样的代码

class TestSqare:public testing::TestWithParam<int>{
protected:int Sqare(int a) {return a*a;}int a;
};TEST_P(TestSqare,case1){a = GetParam();EXPECT_EQ(a*a,Sqare(a));
}INSTANTIATE_TEST_CASE_P(Sare,TestSqare,testing::Values(1,2,3,4));int main(int argc,char* argv[])
{testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}

参考:https://blog.csdn.net/weixin_38988633/article/details/93312474

事件机制

gtest提供事件机制,主要是测试时候,可以在测试案例前后做一些操作

全局事件

要实现全局事件,必须写一个类,继承testing::Environment类,实现里面的SetUp和TearDown方法。

  1. SetUp()方法在所有案例执行前执行

  2. TearDown()方法在所有案例执行后执行

// 全局事件
class FooEnvironment : public testing::Environment
{
public:// 1. SetUp()方法在所有案例执行前执行virtual void SetUp();// 2. TearDown()方法在所有案例执行后执行virtual void TearDown();};void FooEnvironment::SetUp()
{std::cout << "Foo FooEnvironment SetUP" << std::endl;
}void FooEnvironment::TearDown()
{std::cout << "Foo FooEnvironment TearDown" << std::endl;
}int main(int argc, char* argv[])
{testing::AddGlobalTestEnvironment(new FooEnvironment);::testing::InitGoogleTest(&argc, argv);  return RUN_ALL_TESTS();  //return 0;
}

死亡测试

“死亡”指的是程序的崩溃。通常在测试过程中,需要考虑到各种各样的输入,有的输入可能导致程序崩溃;或者某段程序本身存在内存泄漏,指针错误访问等崩溃现象,这时我们需要检查程序是否按照预期的方式挂掉,这也就是所谓的“死亡测试”。gtest的死亡测试能做到在一个安全的环境下执行崩溃的测试案例,同时又对崩溃结果进行验证。

具体会使用如下的两个宏

  1. ASSERT_DEATH(statement, regex`);
  2. EXPECT_DEATH(statement, regex`);
#include "gtest/gtest.h"int Add(int a,int b)
{return a + b;
}void FooDeath()
{int *pInt = NULL;*pInt = 2;
}void FooDeath2()
{
}// 正常测试
TEST(fun, Add)  
{  EXPECT_EQ(1, Add(1,8)); EXPECT_EQ(10, Add(2,8)); EXPECT_EQ(40, Add(24,16)); 
}// gtest会优先运行死亡测试案例
TEST(FooDeathTest, Demo)
{EXPECT_DEATH(FooDeath(), "");
}// 死亡测试,当函数本身是正确的
TEST(Foo2DeathTest, Demo2)
{EXPECT_DEATH(FooDeath2(), "");
}int main(int argc, char* argv[])
{::testing::InitGoogleTest(&argc, argv);  return RUN_ALL_TESTS();//return 0;
}
  • 死亡测试时优先于正常的测试案例的,跟程序放的上下文位置没有关系,死亡测试请使用*DeathTest的测试名
  • 死亡测试,如果真的是"死亡"的,那么会出现绿色的正常的RUN
  • 死亡测试,如果不是真的“死亡”,会出现红色的“failed to die”
//*_EXIT(statement, predicate, regex`) 
void func(int c)
{if(c <= 0)_exit(1);else _exit(2);
}TEST(ExitDeathTest, Demo)
{EXPECT_EXIT(func(-1), testing::ExitedWithCode(1),"");
}TEST(Exit2DeathTest, Demo2)
{EXPECT_EXIT(func(1), testing::ExitedWithCode(1),"");
}int main(int argc, char* argv[])
{::testing::InitGoogleTest(&argc, argv);  return RUN_ALL_TESTS();//return 0;
}

运行参数

使用gtest编写的测试案例通常本身就是一个可执行文件,因此运行起来非常方便。同时,gtest也为我们提供了一系列的运行参数(环境变量、命令行参数或代码里指定),使得我们可以对案例的执行进行一些有效的控制。

gtest三种运行参数

  1. 系统环境变量
  2. 命令行参数
  3. 代码中指定FLAG

面能将特殊结果放入到一个xml文档中

int main(int argc, char* argv[])
{testing::GTEST_FLAG(output) = "xml:";::testing::InitGoogleTest(&argc, argv);  return RUN_ALL_TESTS();
}

命令行参数

–gtest_list_tests

–gtest_list_tests 使用这个参数时,将不会执行里面的测试案例,而是输出一个案例的列表。

–gtest_filter 对执行的测试案例进行过滤,支持通配符

–gtest_filter=Exit*

运行所有测试案例名称为Exit开头的


通过命令行参数还能设置测试案例的输出

  • 设置输出的一些颜色
  • 打印出测试案例的执行时间(默认不打印)
  • 将测试结果输出到另外的文件中(上文有实例)

通过命令行还能对案例异常进行处理

  • 设置当案例失败时,如抛出异常,弹出对话框
  • 调试模式下,案例失败时停止,方面调试

通过文件配置用例执行/* undo*/

自定义测试类

class MyTestClass : public ::testing::Test
{
public:MyTestClass() {}virtual ~MyTestClass() {}virtual void SetUp() {pCal = std::auto_ptr<Cal>(new Cal());}virtual void TearDown() {}
public:std::auto_ptr<Cal> pCal;
};// 第一个参数必须是类名MyTestClass
TEST_F(MyTestClass, test_add)
{pCal->setA(2);pCal->setB(3);EXPECT_TRUE(pCal->add() == 5);
}TEST_F(MyTestClass, test_sub)
{pCal->setA(2);pCal->setB(3);EXPECT_TRUE(pCal->sub() == -1);
}

代码框架

/* undo*/