# GoogleTest 教學 GoogleTest 是 Google 的 C++ 測試框架,可以對 C++ 程式進行單元測試,也就是對程式碼中的單個組件進行測試,例如 function , class,透過進行單元測試,開發者可以快速找到問題所在之處,節省時間成本。因為 C++ 可以兼容 C,因此 GoogleTest 也可用來做 C 的測試。 ## 編寫 GoogleTest 測試程式 這邊寫了一個 gcd 函式進行教學示範 :::spoiler gcd.h ```c= #pragma once #include<stdio.h> #include<stdint.h> #include<math.h> int32_t gcd(int32_t , int32_t); ``` ::: :::spoiler gcd.c ```c= #include "gcd.h" int32_t gcd(int32_t a, int32_t b){ if(a <= 0 || b <= 0)return -1; while(b > 0){ int32_t tmp = b; b = a % b; a = tmp; } return a; } ``` ::: ### 建立測試程式 首先,在專案中創立一個 `hello_test.cc` C++ 檔案,當然你也可以取你喜歡的檔名。 要使用 GoogleTest,當然需要先引入函式庫 ```cpp! #include <gtest/gtest.h> ``` 接下來要引入我們的程式,因為我們寫的是 C,因此需要加上 `extern "C"` ```cpp! extern "C" { #include "gcd.h" } ``` ### 建立 TEST 測試單元 在我們剛剛建立的程式中寫一個測試單元,我們使用TEST巨集建立測試函數,使用方法如下 ```! TEST(測試集, 測試名){ 這裡可以包含任何 C++ 程式,並使用 GoogleTest 的斷言函式檢查數值,如果任何一個斷言巨集錯誤,那就代表這個測試失敗 } ``` GoogleTest的斷言巨集可以到[這裡](https://google.github.io/googletest/reference/assertions.html)找,主要分為兩種,`EXPECT` 和 `ASSERT`,`EXPECT`在錯誤時還會繼續執行後面的程式,而 `ASSERT` 發生錯誤時會直接中止該項測試函數。 這邊列出幾個常用的 - `EXPECT_EQ( val1, val2 )`、`ASSERT_EQ( val1, val2 )` 比較兩個值是否相等 - `EXPECT_NE( val1, val2 )`、`ASSERT_NE( val1, val2 )` 比較兩個值是否不同 - `EXPECT_STREQ( str1, str2 )`、`ASSERT_STREQ( str1, str2 )` 比較兩個字串是否相同 使用 gcd 來進行示範,我創建了一個 vaildinput 和一個 invalidinput 測試,都是 gcd 測試集 ```cpp! TEST(gcd, vaildinput){ EXPECT_EQ(gcd(16, 24), 8); EXPECT_EQ(gcd(9, 3), 3); } TEST(gcd, invalidinput){ EXPECT_EQ(gcd(0, 0), -1); EXPECT_EQ(gcd(0, -1), -1); } ``` :::spoiler 完整程式碼 ```cpp= #include <gtest/gtest.h> extern "C" { #include "gcd.h" } TEST(gcd, vaildinput){ EXPECT_EQ(gcd(16, 24), 8); EXPECT_EQ(gcd(9, 3), 3); } TEST(gcd, invalidinput){ EXPECT_EQ(gcd(0, 0), -1); EXPECT_EQ(gcd(0, -1), -1); } ``` ::: ## 使用CMake ### 建立 CMakeLists.txt GoogleTest 需要使用 CMake 導入與編譯執行,需要確保電腦中有安裝 [CMake](https://cmake.org)。 在專案中建立 `CMakeLists.txt`,這個檔案裡面會寫這個專案的依賴項目。 這兩行是每個 CMakeLists 都必須加的,注意 GoogleTest 要求 CMake 版本最低要3.14 ```cmake= cmake_minimum_required(VERSION 3.14) project(my_project) ``` ### 引入 GoogleTest 在裡面加入這幾行,讓 CMake 從 GitHub 下載 GoogleTest 的檔案 ```cmake= # GoogleTest requires at least C++14 set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip ) FetchContent_MakeAvailable(googletest) ``` 這樣 CMake 就會將 GoogleTest 引入專案當中了。 ### 建立執行檔 首先要啟用測試 ```cmake! enable_testing() ``` 加入你的函式庫 ```cmake! add_library(gcd gcd.c) ``` 最後加入執行檔,連結函式庫還有連結到 GoogleTest ```cmake! add_executable( hello_test hello_test.cc ) target_link_libraries( hello_test gcd gtest_main ) include(GoogleTest) gtest_discover_tests(hello_test) ``` :::spoiler 完整 CMakeLists.txt ```cmake= cmake_minimum_required(VERSION 3.14) project(my_project) # GoogleTest requires at least C++14 set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) include(FetchContent) FetchContent_Declare( googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip ) FetchContent_MakeAvailable(googletest) enable_testing() add_executable( hello_test hello_test.cc ) target_link_libraries( hello_test gcd gtest_main ) include(GoogleTest) gtest_discover_tests(hello_test) ``` ::: ## 編譯並執行 建立一個 build 資料夾,存放編譯後的資料及執行檔 現在專案目錄應該如下 ``` my_project ├── build ├── CMakeLists.txt ├── gcd.c ├── gcd.h └── hello_test.cc ``` 接著告訴 CMake 目標位置 ```bash! cmake -S . -B build ``` 進行建置 ```bash! cmake --build build ``` 恭喜你,現在已經編譯完了,你應該會在 build 資料夾看到執行檔了 進到 build 資料夾中,並執行 ctest 應該就會開始進行測試了 ```bash! cd build ctest ``` 如果成功的話,就可以看到像這樣的輸出 ``` > ctest Test project .../my_project/build Start 1: gcd.vaildinput 1/2 Test #1: gcd.vaildinput ................... Passed 0.01 sec Start 2: gcd.invalidinput 2/2 Test #2: gcd.invalidinput ................. Passed 0.00 sec 100% tests passed, 0 tests failed out of 2 Total Test time (real) = 0.02 sec ``` ## 資源 - GoogleTest https://google.github.io/googletest/ - CMake Tutorial https://cmake.org/cmake/help/latest/guide/tutorial/index.html