C++ 項目之Googletest單元測試

  • 2019 年 10 月 6 日
  • 筆記

C++ 項目之Googletest單元測試

1.Clion集成Googletest單元測試

Googletest – Google Testing and Mocking Framework

源碼下載地址:

https://github.com/google/googletest/releases

Googletest中包含兩個模組,分別是gtest與gmock,需要分別源碼編譯,編譯完後,到指定目錄去拷貝includes文件夾與.so文件到下面路徑的指定位置.

然後項目中創建ext目錄,裡面分為兩塊

  • 第一塊:includes

包含gmock與gtest的include文件,對應於gcc -I參數,頭文件路徑,包含以.h結尾的頭文件

  • 第二塊:libs

包含gmock與gtest的libs文件,對應gcc -L參數,庫文件路徑,裡面包含的是一些.so或.dll等動態或靜態鏈接庫

├── ext  │   ├── includes  │   │   ├── gmock  │   │   └── gtest  │   └── libs  │       ├── gmock  │       └── gtest

上述本地項目路徑配置好後,在CmakeLists.txt中進行配置:

# ext  set(BASE_INCLUDES ext/includes)  set(BASE_LIBS ext/libs)    # googletest  set(GTEST_INCLUDE_DIR ${BASE_INCLUDES}/gtest/include)  set(GMOCK_INCLUDE_DIR ${BASE_INCLUDES}/gmock/include)  set(GTEST_LINK_DIR ${BASE_LIBS}/gtest/lib/)  set(GMOCK_LINK_DIR ${BASE_LIBS}/gmock/lib/)    # 去哪裡找頭文件 相當於gcc/clang 中的-I(i的大寫字母)參數  include_directories(${GTEST_INCLUDE_DIR})  include_directories(${GMOCK_INCLUDE_DIR})    # 去哪裡找庫文件 .so .dll .dylib 相當於gcc 中的-L參數  link_directories(${GTEST_LINK_DIR})  link_directories(${GMOCK_LINK_DIR})

然後為每個test配上鏈接庫即可.

例如,現在有個測試file,文件名為:了l1.cpp

那麼在CmakeLists.txt中配置為:

add_executable(l1 l1.cpp)  target_link_libraries(l1 gtest gtest_main)  

2.gtest之Helloworld

int main(int argc, char* argv[])  {      // 接收命令行參數      testing::InitGoogleTest(&argc, argv);      vector<int> x={1,2,3,5};      // EXPECT_EQ使用      for (int i = 0; i < x.size(); ++i)      {          EXPECT_EQ(x[i], 1) << "Vectors x and y differ at index " << i;      }      RUN_ALL_TESTS();        return 0;  }

例如上述就是個完整的例子,每次運行:

testing::InitGoogleTest(&argc, argv);

然後使用:

RUN_ALL_TESTS();

運行所有的Test,每個Test編寫參考後面斷言.

我們看看運行效果:

l1.cpp:113: Failure  Expected equality of these values:    x[i]      Which is: 2    1  Vectors x and y differ at index 1  l1.cpp:113: Failure  Expected equality of these values:    x[i]      Which is: 3    1  Vectors x and y differ at index 2  l1.cpp:113: Failure  Expected equality of these values:    x[i]      Which is: 5    1  Vectors x and y differ at index 3  [==========] Running 0 tests from 0 test cases.  [==========] 0 tests from 0 test cases ran. (0 ms total)  [  PASSED  ] 0 tests.  [  FAILED  ] 0 tests, listed below:     0 FAILED TESTS

3.gtest初識之斷言

關於斷言Google包裝了一系列EXPECTASSERT的宏,而EXPECT系列和ASSERT系列的區別是:

  • EXPECT 失敗時,案例繼續往下執行。
  • ASSERT 失敗時,直接在當前函數中返回,當前函數中ASSERT後面的語句將不會執行。

例如:

TEST(ASSERTTest, ASSERT_VS_EXPECT)  {      ASSERT_TRUE(10<2);  // ASSERT失敗,直接在當前函數中返回,後面語句不執行      ASSERT_FALSE(10<2);      EXPECT_EQ(6, Foo(310, 18));  }

每個Test是個宏,Test底層源碼如下:

# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)

對應test_case名與test名.

上述程式碼中10<2為False,而使用了ASSERT_TRUE,該Test後面所有內容就不會執行,如果換成EXPECT_TRUE則正常運行!

布爾值檢查

Fatal assertion

Nonfatal assertion

Verifies

ASSERT_TRUE(condition);

EXPECT_TRUE(condition);

condition is true

ASSERT_FALSE(condition);

EXPECT_FALSE(condition);

condition is false

數值型數據檢查

Fatal assertion

Nonfatal assertion

Verifies

ASSERT_EQ(expected,actual);

EXPECT_EQ(expected,actual);

expected == actual

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

字元串檢查

TEST(StringCmpTest, Demo)  {      char* pszCoderZh = "CoderZh";      wchar_t* wszCoderZh = L"CoderZh";      std::string strCoderZh = "CoderZh";      std::wstring wstrCoderZh = L"CoderZh";        EXPECT_STREQ("CoderZh", pszCoderZh);      EXPECT_STREQ(L"CoderZh", wszCoderZh);        EXPECT_STRNE("CnBlogs", pszCoderZh);      EXPECT_STRNE(L"CnBlogs", wszCoderZh);        EXPECT_STRCASEEQ("coderzh", pszCoderZh);      //EXPECT_STRCASEEQ(L"coderzh", wszCoderZh);    不支援        EXPECT_STREQ("CoderZh", strCoderZh.c_str());      EXPECT_STREQ(L"CoderZh", wstrCoderZh.c_str());  }

其中STREQ和STRNE同時支援char和wchar_t類型的,STRCASEEQSTRCASENE卻只接收char*

顯示返回成功或失敗

直接返回成功:SUCCEED();

返回失敗:

Fatal assertion

Nonfatal assertion

FAIL();

ADD_FAILURE();

// 返回成功與否  TEST(ExplicitTest, Demo)  {      ADD_FAILURE() << "這行列印失敗 Sorry"; // None Fatal Asserton,繼續往下執行。        //FAIL(); // Fatal Assertion,不往下執行該案例。      EXPECT_TRUE(1==2)<<"1==2 failed!";      // 為了驗證上述失敗後是否執行下面        SUCCEED();  }

異常檢查

分為三個:

EXPECT_NO_THROW(statement); 不拋出異常

EXPECT_ANY_THROW(statement);拋出任意類型異常

EXPECT_THROW(statement, exception_type); 拋出指定類型異常

TEST(ExceptionTest,et) {      // 拋出任意類型異常      EXPECT_ANY_THROW(10/0); //Expected: 10/0 throws an exception.      // 拋出指定類型異常      EXPECT_THROW(1/0,int); //Expected: 1/0 throws an exception of type int.  }

Predicate Assertions

檢查一個函數的返回值TRUE還是FALSE時,希望能夠輸出傳入的參數是什麼,以便失敗後好跟蹤

例如:

// 預測斷言  bool MN(int m, int n)  {      return m>n;  }  //檢查一個函數的返回值TRUE還是FALSE時,希望能夠輸出傳入的參數是什麼,以便失敗後好跟蹤  TEST(PredicateAssertionTest, Demo)  {      int m = 5, n = 6;      EXPECT_PRED2(MN, m, n); //只提供<=5個參數  傳遞參數要與函數MN對應  }

`EXPECT_PRED2(pred2, val1, val2);ASSERT類似.PRED2可以到PRED5

最多支援5個參數.

浮點型檢查

EXPECT_FLOAT_EQ(expected, actual)EXPECT_DOUBLE_EQ(expected, actual)

ASSERT類似.

對相近的兩個數比較:

EXPECT_NEAR(val1, val2, abs_error);

ASSERT類似.

例如:

// 浮點型  TEST(FloatDoubleTest,Demo) {      ASSERT_DOUBLE_EQ(1.1,1.1);      EXPECT_FLOAT_EQ(1.2,4.0);      EXPECT_NEAR(1.234,1.888,0.9);  //    EXPECT_PRED_FORMAT2(testing::FloatLE, val1, val2);  //    EXPECT_PRED_FORMAT2(testing::DoubleLE, val1, val2);      EXPECT_PRED_FORMAT2(testing::FloatLE,1,0);      // LE表示小於等於 也就是value1<=value2      EXPECT_PRED_FORMAT2(testing::DoubleLE,0.1,0.2);  }

類型檢查

// 類型檢查  template <typename T>  class Tt{  public:      void foo() {          testing::StaticAssertTypeEq<bool, T>();     // 與下面調用一致就不報錯,否則報錯      }  };  TEST(TypeAssertionTest, Demo)  {      Tt<bool> tt;      tt.foo();  }

學習參考自:https://www.cnblogs.com/coderzh/archive/2009/04/06/1430364.html