一文掌握開源單元測(cè)試框架Google Test

我們?cè)陂_發(fā)的過程中,需要做一些驗(yàn)證測(cè)試局劲,來(lái)保證我們的代碼是按照設(shè)計(jì)要求工作的勺拣,這就需要單元測(cè)試了。單元測(cè)試(Unit Test)鱼填,我們稱為“UT測(cè)試”药有。對(duì)于一個(gè)復(fù)雜的系統(tǒng)來(lái)說,需要編寫大量的單元測(cè)試用例苹丸,有人會(huì)覺得這么多的測(cè)試代碼愤惰,將會(huì)花費(fèi)大量的時(shí)間竹祷,影響開發(fā)的進(jìn)度,會(huì)得不償失羊苟。真的是這樣嗎?其實(shí)感憾,對(duì)于越是復(fù)雜的系統(tǒng)就越是需要單元測(cè)試來(lái)保證我們的代碼的開發(fā)質(zhì)量蜡励,及時(shí)測(cè)試出代碼的問題,在開發(fā)階段發(fā)現(xiàn)問題總比在系統(tǒng)發(fā)布之后發(fā)現(xiàn)問題能夠較少的節(jié)省資源或成本阻桅。

對(duì)于單元測(cè)試應(yīng)該是每個(gè)開發(fā)工程師必備的技能凉倚,尤其是高階的開發(fā)工程師會(huì)更加注重UT的重要性。同時(shí)嫂沉,我們?cè)陂_發(fā)功能模塊之前會(huì)考慮到測(cè)試用例的實(shí)現(xiàn)稽寒,這樣自然的就會(huì)考慮到功能模塊的模塊化便于UT的編寫,從這一方面來(lái)說也能提高開發(fā)人員開發(fā)的代碼質(zhì)量趟章。另外杏糙,單元測(cè)試用例還可以作為示例供開發(fā)人員參考,從而能夠更輕松的掌握模塊的使用蚓土。

今天就和大家一起學(xué)習(xí)一個(gè)開源的C++的單元測(cè)試框架Google test宏侍,大家看名字就知道它是由牛逼的Google公司出品。Google Test可以在多種平臺(tái)上使用蜀漆,它可以支持:

Linux谅河、Mac OS X、Windows确丢、Cygwin绷耍、MinGW、Windows Mobile鲜侥、Symbian褂始、PlatformIO等。

安裝和配置

我們可以從github獲取Google Test的源碼描函,如果大家沒有g(shù)ithub賬號(hào)也可以從網(wǎng)盤下載病袄。

github下載地址: https://github.com/google/googletest
網(wǎng)盤下載:關(guān)注公眾號(hào)【W(wǎng)ill的大食堂】回復(fù)【gTest下載】即可獲取下載地址。

因?yàn)槲覀兿螺d到的gTest是源代碼赘阀,還需要將其編譯成庫(kù)文件再進(jìn)行使用益缠。下面將和大家一起學(xué)習(xí)如何在windows環(huán)境下生成gTest的庫(kù)文件。在這之前我們需要安裝CMake和MinGW基公,大家可以參考下面這兩個(gè)文章進(jìn)行安裝幅慌。

將下載的gTest的源碼進(jìn)行解壓轰豆,源碼目錄如下圖所示胰伍。

源碼工程目錄

打開命令行工具cmd齿诞,進(jìn)入源碼的工程目錄,新建一個(gè)build目錄用來(lái)存放構(gòu)建文件骂租,然后祷杈,進(jìn)入build目錄執(zhí)行cmake命令生成Makefile文件。

mkdir build
cd build
cmake -G "MinGW Makefiles" ..
執(zhí)行cmake

生成makefile

Makefile文件生成后渗饮,再執(zhí)行下面的命令mingw32-make編譯庫(kù)文件但汞。編譯成功后就會(huì)發(fā)現(xiàn)有l(wèi)ibgtest.a 和libgtest_main.a兩個(gè)靜態(tài)庫(kù)生成。這里注意互站,Windows下mingw安裝的make工具名稱是mingw32-make而不是make私蕾。

mingw32-make
執(zhí)行mingw32-make命令

接下來(lái)我們?cè)赩S Code寫一個(gè)測(cè)試用例,使用生成的gTest靜態(tài)庫(kù)測(cè)試下胡桃。按下快捷鍵【Ctrl+Shift+p】踩叭,在彈出的搜索框中搜索【C/C++:Edit Configurations】,可以創(chuàng)建c_cpp_properties.json配置文件翠胰。

C/C++:Edit Configurations

在c_cpp_properties.json配置文件添加gTest的頭文件目錄容贝。

添加gTest頭文件目錄

在task.json配置文件中添加gTest頭文件目錄和庫(kù)文件,task.json配置文件可以通過菜單欄中Terminal選項(xiàng)下的【Configure Default Build Task】選項(xiàng)創(chuàng)建之景,可以參照之前的文章嗤疯。

Configure Default Build Task
添加頭文件目錄和庫(kù)文件

上面配置好之后,我們寫個(gè)測(cè)試用例跑一下闺兢。

#include <iostream>
#include <gtest/gtest.h>

int add(int a, int b)
{
    return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

TEST(testcase, test_add)
{
    EXPECT_EQ(add(1,2), 3);
    EXPECT_EQ(sub(1,2), -1);
}

int main(int argc, char **argv)
{  
    std::cout << "run google test --> " << std::endl << std::endl;
    testing::InitGoogleTest(&argc, argv);  
    return RUN_ALL_TESTS(); 
} 

運(yùn)行結(jié)果如下圖所示茂缚,代碼中的TEST是一個(gè)宏,用來(lái)創(chuàng)建測(cè)試用例屋谭,它有test_case_name和test_name兩個(gè)參數(shù)脚囊。分別是測(cè)試用例名和測(cè)試名,在后面的文章中我們會(huì)對(duì)其有更深刻的理解桐磁,這里就不細(xì)說了悔耘。RUN_ALL_TESTS也是一個(gè)宏,它是測(cè)試用例的入口我擂。EXPECT_EQ這個(gè)是一個(gè)斷言相關(guān)的宏衬以,用來(lái)檢測(cè)兩個(gè)數(shù)值是否相等。

運(yùn)行結(jié)果

斷言

除了上面示例里的EXPECT_EQ校摩,在gTest里有很多斷言相關(guān)的宏看峻。斷言可以檢查出某些條件的真假,因此衙吩,我們可以通過它來(lái)判斷被測(cè)試的函數(shù)的成功與否互妓。這里斷言我們主要可以分為兩類:

  • 以"ASSERT_"開頭的斷言,致命性斷言(Fatal assertion)
  • 以"EXPECT_"開頭的斷言 ,非致命性斷言(Nonfatal assertion)

上面的兩種斷言會(huì)在斷言條件不滿足時(shí)會(huì)有區(qū)別冯勉,即當(dāng)不滿足條件時(shí), "ASSERT_"斷言會(huì)在當(dāng)前函數(shù)終止澈蚌,而不會(huì)繼續(xù)執(zhí)行下去;而"EXPECT_"則會(huì)繼續(xù)執(zhí)行灼狰。我們可以通過下面一個(gè)例子來(lái)理解下他們的區(qū)別宛瞄。

#include <iostream>
#include <gtest/gtest.h>

int add(int a, int b)
{
    return a + b;
}

int sub(int a, int b)
{
    return a - b;
}

TEST(testcase, test_expect)
{
    std::cout << "------ test_expect start-----" << std::endl;

    std::cout << "add function start" << std::endl;
    EXPECT_EQ(add(1,2), 2);
    std::cout << "add function end" << std::endl;

    std::cout << "sub function start" << std::endl;
    EXPECT_EQ(sub(1,2), -1);
    std::cout << "sub function end" << std::endl;

    std::cout << "------ test_expect end-----" << std::endl;
}

TEST(testcase, test_assert)
{

    std::cout << "------ test_assert start-----" << std::endl;

    std::cout << "add function start" << std::endl;
    ASSERT_EQ(add(1,2), 2);
    std::cout << "add function end" << std::endl;

    std::cout << "sub function start" << std::endl;
    ASSERT_EQ(sub(1,2), -1);
    std::cout << "sub function end" << std::endl;

    std::cout << "------ test_assert end-----" << std::endl;
}

int main(int argc, char **argv)
{  
    testing::InitGoogleTest(&argc, argv);  
    return RUN_ALL_TESTS(); 
}

從下面的運(yùn)行結(jié)果上看,assert斷言檢查出被測(cè)函數(shù)add不滿足條件交胚,所以程序就沒有繼續(xù)執(zhí)行下去份汗;而expect雖然檢查出被測(cè)試函數(shù)add不滿足條件,但是程序還是繼續(xù)去測(cè)試sub函數(shù)承绸。

assert 和 expect

上面的示例用到的都是判斷相等條件的斷言,還有其他條件檢查的斷言挣轨。主要可以分為布爾檢查军熏,數(shù)值比較檢查,字符串檢查卷扮,浮點(diǎn)數(shù)檢查荡澎,異常檢查等等。下面我們逐一認(rèn)識(shí)這些斷言晤锹。

布爾檢查

布爾檢查主要用來(lái)檢查布爾類型數(shù)據(jù)摩幔,檢查其條件是真還是假。

Assert Expect Description
ASSERT_TRUE(condition) EXPECT_TRUE(condition) 檢查條件是否為真
ASSERT_FALSE(condition) EXPECT_TRUE(condition) 檢查條件是否為假

數(shù)值比較檢查

數(shù)值比較檢查主要用來(lái)比較兩個(gè)數(shù)值之間的大小關(guān)系鞭铆,這里有兩個(gè)參數(shù)或衡。

Assert Expect Description
ASSERT_EQ(val1, val2) EXPECT_EQ(val1, val2) 檢查val1和val2是否相等
ASSERT_NE(val1, val2) EXPECT_NE(val1, val2) 檢查val1和val2是否不相等
ASSERT_LT(val1, val2) EXPECT_LT(val1, val2) 檢查val1是否小于val2
ASSERT_LE(val1, val2) EXPECT_LE(val1, val2) 檢查val1是否小于等于val2
ASSERT_GT(val1, val2) EXPECT_GT(val1, val2) 檢查val1是否大于val2
ASSERT_GE(val1, val2) EXPECT_GE(val1, val2) 檢查val1是否大于val2

字符串檢查

字符串檢查主要用來(lái)比較字符串的內(nèi)容。

Assert Expect Description
ASSERT_STREQ(str1, str2) EXPECT_STREQ(str1, str2) 檢查str1和str2是否相等
ASSERT_STRNE(str1, str2) EXPECT_STRNE(str1, str2) 檢查str1和str2是否不相等
ASSERT_STRCASEEQ(str1, str2) EXPECT_STRCASEEQ(str1, str2) 檢查str1和str2是否相等(忽略大小寫)
ASSERT_STRCASENE(str1, str2) EXPECT_STRCASENE(str1, str2) 檢查str1和str2是否不相等(忽略大小寫)

浮點(diǎn)數(shù)檢查

對(duì)于浮點(diǎn)數(shù)來(lái)說车遂,因?yàn)槠渚仍蚍舛希覀儫o(wú)法確定其是否完全相等,實(shí)際上對(duì)于浮點(diǎn)數(shù)我比較兩個(gè)浮點(diǎn)數(shù)近似相等舶担。

Assert Expect Description
ASSERT_FLOAT_EQ(val1, val2) EXPECT_FLOAT_EQ(val1, val2) 檢查兩個(gè)單精度的值是否相等
ASSERT_DOUBLE_EQ(val1, val2) EXPECT_DOUBLE_EQ(val1, val2) 檢查兩個(gè)雙精度的值是否相等
ASSERT_NEAR(val1, val2, abs_error) EXPECT_NEAR(val1, val2, abs_error) 檢查兩個(gè)浮點(diǎn)數(shù)絕對(duì)差不超過abs_error

異常檢查

異常檢查可以將異常轉(zhuǎn)換成斷言的形式坡疼。

Assert Expect Description
ASSERT_THROW(statement, exception_type) EXPECT_THROW(statement, exception_type) 檢查拋出的給定的異常
ASSERT_ANY_THROW(statement) EXPECT_ANY_THROW(statement) 檢查拋出的任何異常
ASSERT_NO_THROW(statement) EXPECT_NO_THROW(statement) 檢查不拋出異常

除了上面的一些類型的斷言,還有一切其他的常用斷言衣陶。

顯示成功或失敗

這一類斷言會(huì)在測(cè)試運(yùn)行中標(biāo)記成功或失敗柄瑰。它主要有三個(gè)宏:

  • SUCCED():標(biāo)記成功。
  • FAIL() : 標(biāo)記失敗剪况,類似ASSERT斷言標(biāo)記致命錯(cuò)誤教沾;
  • ADD_FAILURE():標(biāo)記,類似EXPECT斷言標(biāo)記非致命錯(cuò)誤译断。
#include <iostream>
#include <gtest/gtest.h>

int divison(int a, int b)
{
    return a / b;
}

TEST(testCaseTest, test0)
{
    std::cout << "start test 0" << std::endl;
    SUCCEED();
    std::cout << "test pass" << std::endl;
}

TEST(testCaseTest, test1)
{
    std::cout << "start test 1" << std::endl;
    FAIL();
    std::cout << "test fail" << std::endl;
}

TEST(testCaseTest, test2)
{
    std::cout << "start test 2" << std::endl;
    ADD_FAILURE();
    std::cout << "test fail" << std::endl;
}


int main(int argc, char **argv)
{  
    testing::InitGoogleTest(&argc, argv);  
    return RUN_ALL_TESTS(); 
} 

執(zhí)行結(jié)果如下:

成功失敗斷言

死亡測(cè)試

死亡測(cè)試是用來(lái)檢測(cè)測(cè)試程序是否按照預(yù)期的方式崩潰详囤。

Assert Expect Description
ASSERT_DEATH(statement, regex) EXPECT_DEATH(statement, regex) 檢查按照代碼給定的方式崩潰

#include <iostream>
#include <gtest/gtest.h>

int divison(int a, int b)
{
    return a / b;
}

TEST(testCaseDeathTest, test_div)
{
    EXPECT_DEATH(divison(1, 0), "");
}
int main(int argc, char **argv)
{  
    testing::InitGoogleTest(&argc, argv);  
    return RUN_ALL_TESTS(); 
} 

上面這個(gè)例子就是死亡測(cè)試,其運(yùn)行結(jié)果如下,這里需要注意的是test_case_name如果使用DeathTest為后綴藏姐,gTest會(huì)優(yōu)先運(yùn)行隆箩。

死亡測(cè)試

測(cè)試事件

在學(xué)習(xí)測(cè)試事件之前,我們先來(lái)了解下三個(gè)概念羔杨,它們分別是測(cè)試程序捌臊,測(cè)試套件,測(cè)試用例兜材。

  • 測(cè)試程序是一個(gè)可執(zhí)行程序蒜埋,它有一個(gè)測(cè)試程序的入口main函數(shù)。
  • 測(cè)試用例是用來(lái)定義需要驗(yàn)證的內(nèi)容祈纯。
  • 測(cè)試套件是測(cè)試用例的集合轧邪,運(yùn)行測(cè)試。

我們回過來(lái)看測(cè)試事件举庶,在GTest中有了測(cè)試事件的這個(gè)機(jī)制执隧,就能能夠在測(cè)試之前或之后能夠做一些準(zhǔn)備/清理的操作。根據(jù)事件執(zhí)行的位置不同户侥,我們可將測(cè)試事件分為三種:

  • TestCase級(jí)別測(cè)試事件:這個(gè)級(jí)別的事件會(huì)在TestCase之前與之后執(zhí)行镀琉;
  • TestSuite級(jí)別測(cè)試事件:這個(gè)級(jí)別的事件會(huì)在TestSuite中第一個(gè)TestCase之前與最后一個(gè)TestCase之后執(zhí)行;
  • 全局測(cè)試事件:這是級(jí)別的事件會(huì)在所有TestCase中第一個(gè)執(zhí)行前蕊唐,與最后一個(gè)之后執(zhí)行屋摔。

這些測(cè)試事件都是基于類的,所以需要在類上實(shí)現(xiàn)替梨。下面我們依次來(lái)學(xué)習(xí)這三種測(cè)試事件钓试。

TestCase測(cè)試事件

TestCase測(cè)試事件,需要實(shí)現(xiàn)兩個(gè)函數(shù)SetUp()和TearDown()副瀑。

  • SetUp()函數(shù)是在TestCase之前執(zhí)行亚侠。
  • TearDown()函數(shù)是在TestCase之后執(zhí)行。

這兩個(gè)函數(shù)是不是有點(diǎn)像類的構(gòu)造函數(shù)和析構(gòu)函數(shù)俗扇,但是切記他們并不是構(gòu)造函數(shù)和析構(gòu)函數(shù)硝烂,只是打個(gè)比方才這么說而已。我們可以借助下面的代碼示例來(lái)加深對(duì)它的理解铜幽。這兩個(gè)函數(shù)是testing::Test的成員函數(shù)滞谢,我們?cè)诰帉憸y(cè)試類時(shí)需要繼承testing::Test。

#include <iostream>
#include <gtest/gtest.h>

class calcFunction
{
public:
    int add(int a, int b)
    {
        return a + b;
    }

    int sub(int a, int b)
    {
        return a - b;
    }
};

class calcFunctionTest : public testing::Test
{
protected:
    virtual void SetUp()
    {
        std::cout << "--> " << __func__ << " <--" <<std::endl;
    }
    virtual void TearDown()
    {
        std::cout << "--> " << __func__ << " <--" <<std::endl;
    }

    calcFunction calc;

};

TEST_F(calcFunctionTest, test_add)
{
    std::cout << "--> test_add start <--" << std::endl;
    EXPECT_EQ(calc.add(1,2), 3);
    std::cout << "--> test_add end <--" << std::endl;
}

TEST_F(calcFunctionTest, test_sub)
{
    std::cout << "--> test_sub start <--" << std::endl;
    EXPECT_EQ(calc.sub(1,2), -1);
    std::cout << "--> test_sub end <--" << std::endl;
}

int main(int argc, char **argv)
{  
    testing::InitGoogleTest(&argc, argv);  
    return RUN_ALL_TESTS(); 
} 

測(cè)試結(jié)果如下除抛,兩個(gè)函數(shù)都是是在每個(gè)TestCase(test_add和test_sub)之前和之后執(zhí)行狮杨。

TestCase事件

TestSuite測(cè)試事件

TestSuite測(cè)試事件,同樣的也需要實(shí)現(xiàn)的兩個(gè)函數(shù)SetUpTestCase()和TearDownTestCase()到忽,而這兩個(gè)函數(shù)是靜態(tài)函數(shù)橄教。這兩個(gè)靜態(tài)函數(shù)同樣也是testing::Test類的成員清寇,我們直接改寫下測(cè)試類calcFunctionTest,添加兩個(gè)靜態(tài)函數(shù)SetUpTestCase()和TearDownTestCase()到測(cè)試類中即可护蝶。

class calcFunctionTest : public testing::Test
{
protected:
    static void SetUpTestCase()
    {
        std::cout<< "--> " <<  __func__ << " <--" << std::endl;
    }

    static void TearDownTestCase()
    {
        std::cout<< "--> " << __func__ << " <--" << std::endl;
    }

    virtual void SetUp()
    {
        std::cout << "--> " << __func__ << " <--" <<std::endl;
    }
    virtual void TearDown()
    {
        std::cout << "--> " << __func__ << " <--" <<std::endl;
    }

    calcFunction calc;

};

改寫好之后华烟,我們?cè)倏匆幌逻\(yùn)行結(jié)果。這兩個(gè)函數(shù)分別是在本TestSuite中的第一個(gè)TestCase之前和最后一個(gè)TestCase之后執(zhí)行持灰。

TestSuite事件

全局測(cè)試事件

全局測(cè)試事件盔夜,也需要繼承一個(gè)類,但是它需要繼承testing::Environment類實(shí)現(xiàn)SetUp()和TearDown()兩個(gè)函數(shù)堤魁。還需要在main函數(shù)中調(diào)用testing::AddGlobalTestEnvironment方法注冊(cè)全局事件喂链。我們直接上代碼吧!


#include <iostream>
#include <gtest/gtest.h>

class calcFunction
{
public:
    int add(int a, int b)
    {
        return a + b;
    }

    int sub(int a, int b)
    {
        return a - b;
    }
};

class calcFunctionEnvironment : public testing::Environment
{
    public:
        virtual void SetUp()
        {
            val = 123;
            std::cout << "--> Environment " << __func__ << " <--" << std::endl;
        }
        virtual void TearDown()
        {
            std::cout << "--> Environment " << __func__ << " <--" << std::endl;
        }

        int val;
};

calcFunctionEnvironment* calc_env;

class calcFunctionTest : public testing::Test
{
protected:
    static void SetUpTestCase()
    {
        std::cout<< "--> " <<  __func__ << " <--" << std::endl;
    }

    static void TearDownTestCase()
    {
        std::cout<< "--> " << __func__ << " <--" << std::endl;
    }

    virtual void SetUp()
    {
        std::cout << "--> " << __func__ << " <--" <<std::endl;
    }
    virtual void TearDown()
    {
        std::cout << "--> " << __func__ << " <--" <<std::endl;
    }

    calcFunction calc;

};

TEST_F(calcFunctionTest, test_add)
{
    std::cout << "--> test_add start <--" << std::endl;
    EXPECT_EQ(calc.add(1,2), 3);
    std::cout << "Global Environment val = " << calc_env->val << std::endl;
    std::cout << "--> test_add end <--" << std::endl;
}

TEST_F(calcFunctionTest, test_sub)
{
    std::cout << "--> test_sub start <--" << std::endl;
    EXPECT_EQ(calc.sub(1,2), -1);
    std::cout << "Global Environment val = " << calc_env->val << std::endl;
    std::cout << "--> test_sub end <--" << std::endl;
}

int main(int argc, char **argv)
{  
    calc_env = new calcFunctionEnvironment;
    testing::AddGlobalTestEnvironment(calc_env);

    testing::InitGoogleTest(&argc, argv);  
    return RUN_ALL_TESTS(); 
} 

從測(cè)試結(jié)果上看妥泉,全局事件的這兩個(gè)函數(shù)分別是在第一個(gè)TestSuite之前和最后一個(gè)TestSuite之后執(zhí)行的椭微。

全局事件

以上三種測(cè)試事件我們可以根據(jù)需要進(jìn)行靈活使用。另外盲链,細(xì)心的同學(xué)會(huì)發(fā)現(xiàn)蝇率,這里測(cè)試用例我們?cè)撚昧薚EST_F這個(gè)宏,這是因?yàn)槔^承了testing::Test,與之對(duì)應(yīng)就需要使用TEST_F宏匈仗。

參數(shù)化

在學(xué)習(xí)gTest參數(shù)化之前我們先看一個(gè)測(cè)試?yán)印?/p>


#include <iostream>
#include <gtest/gtest.h>

class calcFunction
{
public:
    int add(int a, int b)
    {
        std::cout << a << " + " << b << " = " << a + b << std::endl;
        return a + b;
    }

    int sub(int a, int b)
    {
        std::cout << a << " - " << b << " = " << a - b << std::endl;
        return a - b;
    }
};

class calcFunctionTest : public testing::Test
{
protected:
    calcFunction calc;
};

TEST_F(calcFunctionTest, test_add0)
{
    EXPECT_EQ(calc.add(1,2), 3);
}

TEST_F(calcFunctionTest, test_add1)
{
    EXPECT_EQ(calc.add(1,3), 4);
}

TEST_F(calcFunctionTest, test_add2)
{
    EXPECT_EQ(calc.add(2,4), 6);
}

TEST_F(calcFunctionTest, test_add3)
{
    EXPECT_EQ(calc.add(-1,-2), -3);
}

int main(int argc, char **argv)
{  
    testing::InitGoogleTest(&argc, argv);  
    return RUN_ALL_TESTS(); 
} 

示例執(zhí)行結(jié)果:

未參數(shù)化例子

上面的測(cè)試用例中我們寫了多個(gè)測(cè)試用例瓢剿,但是其參數(shù)都是同樣的逢慌,有的實(shí)際應(yīng)用場(chǎng)景可能比這個(gè)程序?qū)懙臏y(cè)試檢查還要多悠轩。寫這么多重復(fù)的代碼實(shí)在是太累了。gTest提供了一個(gè)非常友好的工具攻泼,將這些測(cè)試的值進(jìn)行參數(shù)化火架,就不用寫那么多重復(fù)的代碼了。
如何對(duì)其進(jìn)行參數(shù)化呢忙菠?直接上代碼何鸡,我們?cè)賮?lái)看下面一個(gè)例子。


#include <iostream>
#include <gtest/gtest.h>

class calcFunction
{
public:
    int add(int a, int b)
    {
        std::cout << a << " + " << b << " = " << a + b << std::endl;
        return a + b;
    }

    int sub(int a, int b)
    {
        std::cout << a << " - " << b << " = " << a - b << std::endl;
        return a - b;
    }
};

struct TestParam
{
    int a;
    int b;
    int c;
};

class calcFunctionTest : public ::testing::TestWithParam<struct TestParam>
{
protected:
    calcFunction calc;
    TestParam param;

    virtual void SetUp()
    {
        param.a = GetParam().a;
        param.b = GetParam().b;
        param.c = GetParam().c;
    }

};

TEST_P(calcFunctionTest, test_add)
{
    EXPECT_EQ(calc.add(param.a, param.b), param.c);
}

INSTANTIATE_TEST_CASE_P(addTest, calcFunctionTest, ::testing::Values( TestParam{1, 2 , 3}, 
                                                                      TestParam{1, 3 , 4},
                                                                      TestParam{2, 4 , 6},
                                                                      TestParam{-1, -2 , -3}));

int main(int argc, char **argv)
{  
    testing::InitGoogleTest(&argc, argv);  
    return RUN_ALL_TESTS(); 
} 

執(zhí)行結(jié)果和前面的例子一樣牛欢。

參數(shù)化例子

從這個(gè)例子中骡男,我們不難發(fā)現(xiàn)和之前的測(cè)試程序有一些不同。這里繼承了::testing::TestWithParam<T>類傍睹,參數(shù)T就是需要參數(shù)化的數(shù)據(jù)類型隔盛,這個(gè)例子里參數(shù)化數(shù)據(jù)類型是TestParam結(jié)構(gòu)體。這里還需要使用另外一個(gè)宏TEST_P而不是TEST_F這個(gè)宏拾稳,它的兩個(gè)參數(shù)和TEST_F和TEST一致吮炕。另外,程序中還增加一個(gè)宏INSTANTIATE_TEST_CASE_P用來(lái)輸入測(cè)試參數(shù)访得,它有三個(gè)參數(shù)(第一個(gè)參數(shù)大家可任意取名龙亲,第二個(gè)參數(shù)是test_case_name和TEST_P宏的名稱一致,第三個(gè)參數(shù)是需要傳遞的參數(shù))。

以上就是今天的所有內(nèi)容鳄炉,感謝大家耐心的閱讀杜耙,希望大家都有所收獲,愿大家代碼無(wú)bug迎膜。

本文首發(fā)公眾號(hào):Will的大食堂泥技,轉(zhuǎn)載請(qǐng)聯(lián)系微信:yuzaiduzhong。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末磕仅,一起剝皮案震驚了整個(gè)濱河市珊豹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌榕订,老刑警劉巖店茶,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異劫恒,居然都是意外死亡贩幻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門两嘴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)丛楚,“玉大人,你說我怎么就攤上這事憔辫∪ば” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵贰您,是天一觀的道長(zhǎng)坏平。 經(jīng)常有香客問我,道長(zhǎng)锦亦,這世上最難降的妖魔是什么舶替? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮杠园,結(jié)果婚禮上顾瞪,老公的妹妹穿的比我還像新娘。我一直安慰自己抛蚁,他們只是感情好陈醒,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著篮绿,像睡著了一般孵延。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上亲配,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天尘应,我揣著相機(jī)與錄音惶凝,去河邊找鬼。 笑死犬钢,一個(gè)胖子當(dāng)著我的面吹牛苍鲜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播玷犹,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼混滔,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了歹颓?” 一聲冷哼從身側(cè)響起坯屿,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎巍扛,沒想到半個(gè)月后领跛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡撤奸,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年吠昭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胧瓜。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡矢棚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出府喳,到底是詐尸還是另有隱情蒲肋,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布劫拢,位于F島的核電站肉津,受9級(jí)特大地震影響强胰,放射性物質(zhì)發(fā)生泄漏舱沧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一偶洋、第九天 我趴在偏房一處隱蔽的房頂上張望熟吏。 院中可真熱鬧,春花似錦玄窝、人聲如沸牵寺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)帽氓。三九已至,卻和暖如春俩块,著一層夾襖步出監(jiān)牢的瞬間黎休,已是汗流浹背浓领。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留势腮,地道東北人联贩。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像捎拯,于是被迫代替她去往敵國(guó)和親泪幌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348