gtest的介紹和使用

一、什仫是gtest
gtest是一個跨平臺的(Liunx、Mac OS X、Windows、Cygwin、Windows CE and Symbian)C++單元測試框架,由google公司發佈。gtest是爲在不同平臺上爲編寫C++測試而生成的。它提供了豐富的斷言、致命和非致命判斷、參數化、”死亡測試”等等。
瞭解了什仫是gtest之後下面讓我們來學習gtest的一些使用規則吧!
一、gtest系列之TEST宏

TEST(test_case_name, test_name)
TEST_F(test_fixture,test_name)  //多個測試場景需要相同數據配置的情況,用TEST_F。TEST_F  test fixture,測試夾具,測試套,承擔了一個註冊的功能。
  • 1
  • 2

TEST宏的作用是創建一個簡單測試,它定義了一個測試函數,在這個函數裏可以使用任何C++代碼並使用提供的斷言來進行檢查。後續文章還會提到TEST_P這個宏,在這裏就先不介紹了。


二、gtest系列之斷言
gtest中斷言的宏可以分爲兩類:一類是ASSERT宏,另一類就是EXPECT宏了。
1、ASSERT_系列:如果當前點檢測失敗則退出當前函數
2、EXPECT_系列:如果當前點檢測失敗則繼續往下執行
如果你對自動輸出的錯誤信息不滿意的話,也是可以通過operator<<能夠在失敗的時候打印日誌,將一些自定義的信息輸出。
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)
13>、EXPECT_系列,也是具有類似的宏結構的
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

下面我們來做一個測試,實現一個求絕對值的函數,並在TEST宏裏面使用ASSERT來進行測試不同類型的數據。

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

int Abs(int x)
{
     return x > 0 ? x : -x;
}

TEST(IsAbsTest,HandlerTrueReturn)
{
    ASSERT_TRUE(Abs(1) == 1) << "Abs(1)=1";  //ASSERT_TRUE期待結果是true,operator<<輸出一些自定義的信息
    ASSERT_TRUE(Abs(-1) == 1) << "Abs(-1)=1";
    ASSERT_FALSE(Abs(-2) == -2);  //期待結果是false
    ASSERT_EQ(Abs(1),Abs(-1));
    ASSERT_NE(Abs(-1),0);
    ASSERT_LT(Abs(-1),2);
    ASSERT_GT(Abs(-1),0);
    ASSERT_LE(Abs(-1),2);
    ASSERT_GE(Abs(-1),0);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

1>、正確測試

正確測試

2>、將第一條語句寫成: ASSERT_FALSE(Abs(1) == 1) << “Abs(1)=1”,此時再次測試就會打印出自定義的出錯信息了。

錯誤測試


三、gtest系列之事件機制
“事件” 本質是框架給你提供了一個機會, 讓你能在這樣的幾個機會來執行你自己定製的代碼, 來給測試用例準備/清理數據。gtest提供了多種事件機制,總結一下gtest的事件一共有三種:
1、TestSuite事件
需要寫一個類,繼承testing::Test,然後實現兩個靜態方法:SetUpTestCase方法在第一個TestCase之前執行;TearDownTestCase方法在最後一個TestCase之後執行。
2、TestCase事件
是掛在每個案例執行前後的,需要實現的是SetUp方法和TearDown方法。SetUp方法在每個TestCase之前執行;TearDown方法在每個TestCase之後執行。
3、全局事件
要實現全局事件,必須寫一個類,繼承testing::Environment類,實現裏面的SetUp和TearDown方法。SetUp方法在所有案例執行前執行;TearDown方法在所有案例執行後執行。
例如全局事件可以按照下列方式來使用:
除了要繼承testing::Environment類,還要定義一個該全局環境的一個對象並將該對象添加到全局環境測試中去。

全局事件

下面我們再來做一個測試實例,測試Map的find()和size()函數並通過繼承testing::Test來實現。
此時的TEST宏必須寫成TEST_F,而且它的第一個參數必須與類名一致,
TEST_F test fixture,測試夾具,測試套,承擔了一個註冊的功能。
代碼實現如下:

class TestMap:public testing::Test
{
public:
    //添加日誌
    static void SetUpTestCase()
    {
        cout<<"SetUpTestCase"<<endl;
    }
    static void TearDownTestCase()
    {
        cout<<"TearDownTestCase"<<endl;
    }
    virtual void SetUp()   //TEST跑之前會執行SetUp
    {
        cout<<"SetUp"<<endl;
        test_map.insert(make_pair(1,0));
        test_map.insert(make_pair(2,1));
        test_map.insert(make_pair(3,2));
        test_map.insert(make_pair(4,3));
        test_map.insert(make_pair(5,4));
    }
    virtual void TearDown() //TEST跑完之後會執行TearDown
    {
        cout<<"TearDown"<<endl;
        test_map.clear();
    }
    map<int,int> test_map;
};
TEST_F(TestMap,Find)   //此時使用的是TEST_F宏
{
    map<int,int>::iterator it=test_map.find(1);
    ASSERT_NE(it,test_map.end());
}
TEST_F(TestMap,Size)
{
    ASSERT_EQ(test_map.size(),5);
}

int main(int argc,char *argv[])
{
    testing::InitGoogleTest(&argc, argv);//將命令行參數傳遞給gtest
    return RUN_ALL_TESTS();   //RUN_ALL_TESTS()運行所有測試案例
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

四、gtest系列之死亡測試
這裏的”死亡”指的是程序的奔潰。通常在測試的過程中,我們需要考慮各種各樣的輸入,有的輸入可能直接導致程序奔潰,這個時候我們就要檢查程序是否按照預期的方式掛掉,這也就是所謂的”死亡測試”。
死亡測試所用到的宏:

1>、ASSERT_DEATH(參數1,參數2),程序掛了並且錯誤信息和參數2匹配,此時認爲測試通過。如果參數2爲空字符串,則只需要看程序掛沒掛即可。
2>、ASSERT_EXIT(參數1,參數2,參數3),語句停止並且錯誤信息和被提前給的信息匹配。
  • 1
  • 2

下面我們再來做一個測試實例,測試當程序出問題時候死亡測試如何使用?

死亡測試

五、一個關於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();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153

點擊此處查看源碼

以上測試用例都是在Linux系統下測試的,讀者需自行在Linux下安裝gtest。
在這裏就分享結束了~~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章