GTest

参考链接:
https://blog.csdn.net/linhai1028/article/details/81675724
https://www.cnblogs.com/helloworldcode/p/9606838.html

一.gtest简介
是Google的一套用于编写C++测试的框架,可以运行在很多平台上(包括Linux、Mac OS X、Windows、Cygwin等等)。基于xUnit架构。支持很多好用的特性,包括自动识别测试、丰富的断言、断言自定义、死亡测试、非终止的失败、生成XML报告等等。
主要用于单元测试.

二.下载安装

git clone https://github.com/google/googletest.git
cd googletest
cmake ..
make

sudo cp libgtest*.a  /usr/lib 

sudo cp –a include/gtest /usr/include



然后在build/lib目录下会生成:libgmock.a  libgmock_main.a  libgtest.a  libgtest_main.a  
最后我们再 sudo make install

三.gtest之断言 :ASSERT宏 与 EXPECT宏

  1. ASSERT_系列:如果当前点检测失败则退出当前的函数
  2. EXPECT_系列:如果当前点检测失败则继续往下执行
  3. 如果我们对gtest自带的输出不满意的话,可以通过operator<<能够在失败的时候打印日志,将一些自定义的信息输出,如下:
ASSERT_TRUE(Abs(1) == 1); 
ASSERT_TRUE(Abs(1) == 1) << "Abs(1)=1";

其中Abs()是自定义的来取绝对值的函数,与<<无关

ASSERT系列的宏:

bool值检查
1>、ASSERT_TRUE(参数),期待结果是true
2>、ASSERT_FALSE(参数),期待结果是false
数值型数据检查
3>、ASSERT_EQ(参数1,参数2),传入的是需要比较的两个数  equal
4>、ASSERT_NE(参数1,参数2),not equal,不等于才返回true
5>、ASSERT_LT(参数1,参数2),less than,小于才返回true
6>、ASSERT_GT(参数1,参数2),greater than,大于才返回true
7>、ASSERT_LE(参数1,参数2),less equal,小于等于才返回true
8>、ASSERT_GE(参数1,参数2),greater equal,大于等于才返回true
字符串检查
9>、ASSERT_STREQ(expected_str, actual_str),两个C风格的字符串相等才正确返回
10>、ASSERT_STRNE(str1, str2),两个C风格的字符串不相等时才正确返回
11>、ASSERT_STRCASEEQ(expected_str, actual_str)
12>、ASSERT_STRCASENE(str1, str2)


EXPECT_系列,也是具有类似的宏结构的,如EXPECT_TRUE()
不同的是,及时遇到失败,还是会继续的向下执行.

使用实例:

  1 #include<iostream>                                                                                                                       
  2 using namespace std;
  3 #include"gtest/gtest.h"
  4 
  5 int Abs(int x)
  6 {
  7     return x > 0 ? x:(x*-1);
  8 }
  9 
 10 // TEST宏有两个参数,第一个是TestSuiteName,第二个是TestCaseName
 11 TEST(IsAbsTest,HandlerTrueReturn)
 12 {
 13         ASSERT_EQ(Abs(1), 1);  //ASSERT_TRUE期待结果是true,operator<<输出一些自定义的信息
 14         ASSERT_TRUE(Abs(-1) == 1) << "Abs(-1)=1";
 15         ASSERT_FALSE(Abs(-2) == -2);  //期待结果是false
 16         ASSERT_EQ(Abs(1),Abs(-1));
 17         ASSERT_NE(Abs(-1),0);
 18         ASSERT_LT(Abs(-1),2);
 19         ASSERT_GT(Abs(-1),0);
 20         ASSERT_LE(Abs(-1),2);
 21         ASSERT_GE(Abs(-1),0);
 22 }
 23 
 24 int main(int argc,char **argv){
 25   testing::InitGoogleTest(&argc,argv);
 26     return RUN_ALL_TESTS();
 27 }
//需要包括这个主函数,而且主函数的内容是固定不变的

编译

g++ main.cc -lpthread -lgtest   
//需要链接线程和gtest库

如果我们不在源文件中写main()函数的话,编译的时候需要链接libgtest_main.a库
g++ main.cc -lgtest -lgtest_main -lpthread

结果:

Running main() from /home/txp/mydir/gtest/googletest/googletest/src/gtest_main.cc
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from IsAbsTest
[ RUN      ] IsAbsTest.HandlerTrueReturn
[       OK ] IsAbsTest.HandlerTrueReturn (0 ms)
[----------] 1 test from IsAbsTest (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.

四.gtest之事件机制

事件:框架给我们提供的一个机会,让我们能在这几个机会来执行自己制定的代码买来给测试用例准备/清理数据.

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

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

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

还需要告诉gtest添加这个全局事件,我们需要在main函数中通过testing::AddGlobalTestEnvironment方法将事件挂进来,也就是说,我们可以写很多个这样的类,然后将他们的事件都挂上去。

TestSuite事件
我们需要写一个类,继承testing::Test,然后实现两个静态方法

  1. SetUpTestCase() 方法在第一个TestCase之前执行

  2. TearDownTestCase() 方法在最后一个TestCase之后执行

在编写测试案例时,我们需要使用TEST_F这个宏,第一个参数必须是我们上面类的名字,代表一个TestSuite。

TestCase事件
TestCase事件是挂在每个案例执行前后的,实现方式和上面的几乎一样,不过需要实现的是SetUp方法和TearDown方法:

  1. SetUp()方法在每个TestCase之前执行

  2. TearDown()方法在每个TestCase之后执行

#include<gtest/gtest.h>
#include<map>
#include<iostream>
using namespace std;
class Student{
public:
    Student(){
        age=0;
    }
    Student(int a){
        age=a;
    }
    void print(){
    cout<<"*********** "<<age<<" **********"<<endl;;
        }  
private:
    int age;
};
class FooEnvironment : public testing::Environment{
public:
    virtual void SetUp()
    {
        std::cout << "Foo FooEnvironment SetUP" << std::endl;
    }
    virtual void TearDown()
    {
        std::cout << "Foo FooEnvironment TearDown" << std::endl;
    }
};
static Student *s;
//在第一个test之前,最后一个test之后调用SetUpTestCase()和TearDownTestCase()
class TestMap:public testing::Test
{
public:
    static void SetUpTestCase()
    {
        cout<<"SetUpTestCase()"<<endl;
    s=new Student(23);
    }
 
    static void TearDownTestCase()
    {
    delete s;
        cout<<"TearDownTestCase()"<<endl;
    }
    void SetUp()
    {
        cout<<"SetUp() is running"<<endl;
         
    }
    void TearDown()
    {
        cout<<"TearDown()"<<endl;
    } 
};
 
TEST_F(TestMap, Test1)
 {
 
    // you can refer to s here
    s->print();
}
int main(int argc, char** argv)
{
    testing::AddGlobalTestEnvironment(new FooEnvironment);
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

在这里插入图片描述
五.gtest之死亡测试

”死亡”指的是程序的奔溃。通常在测试的过程中,我们需要考虑各种各样的输入,有的输入可能直接导致程序奔溃,这个时候我们就要检查程序是否按照预期的方式挂掉,这也就是所谓的”死亡测试”。

1>、ASSERT_DEATH(参数1,参数2)
程序挂了并且错误信息和参数2匹配,此时认为测试通过。如果参数2为空字符串,则只需要看程序挂没挂即可。

2>、ASSERT_EXIT(参数1,参数2,参数3)
语句停止并且错误信息和被提前给的信息匹配。
#include<gtest/gtest.h>
int func() //访问空指针
{
	int *p=NULL;
	*ptr = 100;
	return 0;
}

TEST (FuncDeathTest,Nullptr)
{
	ASSERT_DEATH(func()," ");
}

六.gtest之参数测试

当考虑多次要为被测函数传入不同的值的情况时,可以按下面的方式去测试。必须添加一个类,继承testing::TestWithParam。其中T就是你需要参数化的参数类型,如下面的案例是int型参数。(官方文档上的案例)

#include<gtest/gtest.h>
// Returns true iff n is a prime number.
bool IsPrime(int n)
{
    // Trivial case 1: small numbers
    if (n <= 1) return false;
    // Trivial case 2: even numbers
    if (n % 2 == 0) return n == 2;
    // Now, we have that n is odd and n >= 3.
    // Try to divide n by every odd number i, starting from 3
    for (int i = 3; ; i += 2) {
        // We only have to try i up to the squre root of n
        if (i > n/i) break;
        // Now, we have i <= n/i < n.
        // If n is divisible by i, n is not prime.
        if (n % i == 0) return false;
    }
    // n has no integer factor in the range (1, n), and thus is prime.
    return true;
}
class IsPrimeParamTest : public::testing::TestWithParam<int>{};
TEST_P(IsPrimeParamTest, HandleTrueReturn)
{
 int n =  GetParam();
 EXPECT_TRUE(IsPrime(n));
}
//被测函数须传入多个相关的值
INSTANTIATE_TEST_CASE_P(TrueReturn, IsPrimeParamTest, testing::Values(3, 5, 11, 23, 17));
int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

七.一个关于gtest的例子

#include<iostream>
using namespace std;
#include<gtest/gtest.h>

struct LinkNode
{
    int _data;
    LinkNode *_next;
    LinkNode(const int& data)
        :_data(data)
        ,_next(NULL)
    {}
};

class Link
{
public:
    Link()
        :pHead(new LinkNode(0))
    {}
    void PushBack(const int& data)
    {
        if(pHead == NULL)
            return ;
        LinkNode *newNode=new LinkNode(data);
        if(pHead->_next == NULL){  //第一次插入结点
            pHead->_next=newNode;
        }
        else{  //找到最后一个结点直接尾插
            LinkNode *cur=pHead->_next;
            while(cur->_next){
                cur=cur->_next;
            }
            cur->_next=newNode;
        }
    }

    void PopBack()
    {
        if(pHead == NULL)
            return ;
        LinkNode *cur=pHead;
        LinkNode *prev=NULL;
        while(cur->_next)
        {
            prev=cur;
            cur=cur->_next;
        }
        prev->_next=NULL;
        delete cur;
    }

    LinkNode *FindNode(const int& data)
    {
        if(pHead == NULL)
            return NULL;
        LinkNode *cur=pHead->_next;
        while(cur)
        {
            if(cur->_data == data)
                return cur;
            cur=cur->_next;
        }
        return NULL;
    }

    bool Delete(int data)
    {
        LinkNode *pos=FindNode(data);
        if(pos == NULL)
            return false;
        LinkNode *cur=pHead->_next;
        while(cur->_next != pos)
        {
            cur=cur->_next;
        }
        cur->_next=pos->_next;
        delete pos;
        return true;
    }

    void Destroy()
    {
        if(pHead == NULL)
            return;
        LinkNode *cur=pHead->_next;
        while(cur)
        {
            LinkNode *del=cur;
            cur=cur->_next;
            delete del;
            del=NULL;
        }
        delete pHead;  //删除头结点
    }
    LinkNode *pHead;
};

class TestLink:public testing::Test
{
public:
    virtual void SetUp()
    {
        cout<<"SetUp"<<endl;
        for(int i=1;i<=5;i++){
            link.PushBack(i);
        }
    }
    virtual void TearDown()
    {
        cout<<"TearDown"<<endl;
        link.Destroy();
    }
    Link link;
};

TEST_F(TestLink,PushBack)
{
    ASSERT_FALSE(link.pHead == NULL);
    link.PushBack(9);
    LinkNode *res=link.FindNode(9);
    ASSERT_FALSE(res == NULL);
}

TEST_F(TestLink,PopBack)
{
    for(int i=1;i<=5;i++){
        link.PopBack();
    }
}

TEST_F(TestLink,FindNode)
{
    ASSERT_TRUE(link.FindNode(3));
    ASSERT_TRUE(link.FindNode(2));
    ASSERT_TRUE(link.FindNode(4));
    ASSERT_TRUE(link.FindNode(5));
    ASSERT_TRUE(link.FindNode(1));
    ASSERT_FALSE(link.FindNode(7));
}

TEST_F(TestLink,Delete)
{
    ASSERT_FALSE(link.pHead == NULL);
    ASSERT_TRUE(link.Delete(3) == true);
    ASSERT_TRUE(link.Delete(9) == false);
}

int main(int argc,char *argv[])
{
    testing::InitGoogleTest(&argc,argv);
    return RUN_ALL_TESTS();
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值