gtest的安裝和使用


Linux x86環境下

一,gtest安裝

下載gtest源碼包:gtest-1.7.0.zip

解壓后進入gtest-1.7.0目錄

cmake CMakeLists.txt

make 后生成兩個靜態庫:libgtest.a libgtest_main.a

sudo cp libgtest*.a  /usr/lib 

sudo cp –a include/gtest /usr/include

 

下面是進入到sample目錄下編譯用例

cd sample

g++ sample1.cc sample1_unittest.cc -lgtest -lgtest_main -lpthread -o test1

g++ sample1.cc sample3-inl.h sample5_unittest.cc -lgtest -lgtest_main -lpthread -o test5

由於sample1.cc和sample1_unittest.cc文件中沒有編寫main函數,這里需要鏈接libgtest_main.a庫

 

二,gtest使用

http://www.cnblogs.com/coderzh/archive/2009/04/06/1430364.html

 

gtest 即 Google C++單元測試框架

單元測試一般由編碼人員自己完成,它的目的是隔離程序部件,並證明這些單個部件滿足預期的功能。

它提供了豐富的斷言、致命和非致命失敗判斷,能進行值參數化測試、類型參數化測試、“死亡測試”

1,斷言

ASSERT_* 系列的斷言,當檢查點失敗時,退出當前函數(注意:並非退出當前案例)

EXPECT_* 系列的斷言,當檢查點失敗時,繼續往下執行。

 

<1>布爾類型檢查

ASSERT_TRUE(condition)  ASSERT_FALSE(condition)

<2>數值類型檢查

ASSERT_EQ(expected, actual);

ASSERT_NE(val1, val2);

ASSERT_LT(val1, val2);

ASSERT_LE(val1, val2);

ASSERT_GT(val1, val2);

ASSERT_GE(val1, val2);

<3>字符串檢查

ASSERT_STREQ(expected_str, actual_str);

ASSERT_STRNE(str1, str2);

ASSERT_STRCASEEQ(expected_str, actual_str);

ASSERT_STRCASENE(str1, str2);

 

 

一個簡單的測試案例,可以參考sample/sample1.cc 和sample1_unittest.cc

另外sample2 是對類的接口函數的測試。

首先是一個求最大公約數的函數

int Foo(int a, int b)
{
    if (a == 0 || b == 0)
    {
        throw "don't do that";
    }
    int c = a % b;
    if (c == 0)
        return b;
    return Foo(b, c);
}

下面是對這個函數寫一個簡單的測試樣例

#include <gtest/gtest.h>

TEST(FooTest, HandleNoneZeroInput)
{
    EXPECT_EQ(2, Foo(4, 10));
    EXPECT_EQ(6, Foo(30, 18));
}

每個案例(TEST或TEST_F)應該是相互獨立,互不影響的。

TEST宏有兩個參數,第一個是TestSuiteName,第二個是TestCaseName

然后在main中添加如下代碼讓我們的案例運行起來。

int _tmain(int argc, _TCHAR* argv[])
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

也可以不寫main函數,直接在編譯的時候鏈接libgtest_main.a庫

 

2,gtest提供了多種事件機制,非常方便我們在案例之前或之后做一些操作。總結一下gtest的事件一共有3種:

<1>全局的,所有案例執行前后。

<2>TestSuite級別的,在某一批案例中第一個案例前,最后一個案例執行后。

<3> TestCase級別的,每個TestCase前后。

 

這里主要介紹TestCase事件

TestCase事件是掛在每個案例執行前后的,不過需要實現的是SetUp方法和TearDown方法:

1. SetUp()方法在每個TestCase之前執行

2. TearDown()方法在每個TestCase之后執行

要寫一個類,這個類繼承 testing::Test類。

class FooCalcTest:public testing::Test
{
protected:
    virtual void SetUp()
    {
        m_foo.Init();
    }
    virtual void TearDown()
    {
        m_foo.Finalize();
    }

    FooCalc m_foo;
};

TEST_F(FooCalcTest, HandleNoneZeroInput)
{
    EXPECT_EQ(4, m_foo.Calc(12, 16));
}

TEST_F(FooCalcTest, HandleNoneZeroInput_Error)
{
    EXPECT_EQ(5, m_foo.Calc(12, 16));
}

寫測試案例時,使用TEST_F則開始測試前調用SetUp,結束案例后調用TearDown。也可以在這個類中定義其他的測試函數,供TEST_F調用。TEST_F的第一個參數類的名字,第二個參數是測試案例名。

gtest源碼中的sample3也用的是TestCase事件。這個例子中定義了一個Queue模板,在QueueTest類中定義了SetUp函數和一個用來測試Map的MapTester函數。

 

3,參數化測試(mytest2)

首先必須添加一個類,繼承testing::TestWithParam<T>,其中T就是你需要參數化的參數類型,這里是int。

然后使用TEST_P定義參數化案例。在TEST_P宏里,使用GetParam()獲取當前的參數的具體值。

最后 使用INSTANTIATE_TEST_CASE_P這宏來告訴gtest你要測試的參數范圍

#include <gtest/gtest.h>

class IsPrimeParamTest : public::testing::TestWithParam<int>
{

};

// 不使用參數化測試,就需要像這樣寫五次
TEST(IsPrimeTest, HandleTrueReturn1)
{
    EXPECT_TRUE(IsPrime(3));
    EXPECT_TRUE(IsPrime(5));
    EXPECT_TRUE(IsPrime(11));
    EXPECT_TRUE(IsPrime(23));
    EXPECT_TRUE(IsPrime(17));
}

// 使用參數化測試,只需要:
TEST_P(IsPrimeParamTest, HandleTrueReturn2)
{
    int n =  GetParam();
    EXPECT_TRUE(IsPrime(n));
}

// 定義參數
INSTANTIATE_TEST_CASE_P(TrueReturn, IsPrimeParamTest, testing::Values(3, 5, 11, 23, 17));

 

INSTANTIATE_TEST_CASE_P宏的三個參數:

第一個參數是測試案例的前綴,可以任意取。

第二個參數是測試案例的名稱,需要和之前定義的參數化的類的名稱相同,如:IsPrimeParamTest

第三個參數是可以理解為參數生成器,上面的例子使用test::Values表示使用括號內的參數。Google提供了一系列的參數生成的函數:

Range(begin, end[, step])

范圍在begin~end之間,步長為step,不包括end

Values(v1, v2, ..., vN)

v1,v2到vN的值

ValuesIn(container) and ValuesIn(begin, end)

從一個C類型的數組或是STL容器,或是迭代器中取值

Bool()

取false 和 true 兩個值

Combine(g1, g2, ..., gN)

這個比較強悍,它將g1,g2,...gN進行排列組合,g1,g2,...gN本身是一個參數生成器,每次分別從g1,g2,..gN中各取出一個值,組合成一個元組(Tuple)作為一個參數。

說明:這個功能只在提供了<tr1/tuple>頭的系統中有效。gtest會自動去判斷是否支持tr/tuple,如果你的系統確實支持,而gtest判斷錯誤的話,你可以重新定義宏GTEST_HAS_TR1_TUPLE=1。

 

4,命令行參數

--gtest_output=xml:dir:\foo.xml

指定輸出到dir\foo.xml,不指定則輸出到當前目錄。也可以由系統變量GTEST_OUTPUT指定

--gtest_list_tests

使用這個參數時,將不會執行里面的測試案例,而是輸出一個案例的列表。

--gtest_filter

對執行的測試案例進行過濾,支持通配符

 

 

好的單元測試具備以下特點:

1,  獨立:即該測試用例的測試結果不受其他測試的影響

2,  有效的組織架構,清晰的命名:各個測試用例針對不同的測試對象,而對單個測試對象而言,又可能有多個測試用例對應該對象的多個功能。好的習慣是把這些用例以層次結構的形式組織起來,並使用清晰的命名,使得我們通過閱讀用例名稱即可明了該用例的功能

3,  可移植、可復用

4,  當用例失敗時,提供盡可能多的有效信息

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM