unit testing 的第一步:使用 gcov/lcov 統計 c++ project 的 testing coverage
在寫 unit testing 時偶爾會不小心漏掉了一些 case 導致測試不完整,coverage report 可以幫我們做初步的檢查,確保測試程式有一定程度的品質,還可以順便抓出沒有用到的 code
這次的範例包含了一個
gcc --coverage
為了產生分析 coverage 必要的資料,我們必須在 compiler 時加上--coverage
的參數,才能夠在程式執行時,得知每行程式碼是否有被跑到,在 link 時也要加上 --coverage
。重要的是還要將最佳化關掉,避免最佳化影響統計的結果,可以參考 CMakeLists.txt
,我使用的 gcc 版本為 7.4.0。SET(GCC_COVERAGE_COMPILE_FLAGS "-g -O0 --coverage")
SET(GCC_COVERAGE_LINK_FLAGS "--coverage")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
透過這樣的參數來 compile 後,可以發現所有 *.o
的旁邊都多出了 *.gcno
的檔案,可以想成他記錄了每一行的程式碼,之後要用來比對是否有哪一行沒有被執行到範例
完整的 code 一樣放在 github這次的範例包含了一個
TestClass
在 libarary 中,裡面有 private function 和會被測試到與不會被測試到的 function 各一個void TestClass::TestedFunction(bool cond1, bool cond2) const
{
PrivateFunction(cond1, cond2);
}
void TestClass::UntestedFunction() const
{
PrivateFunction(false, false);
}
void TestClass::PrivateFunction(bool cond1, bool cond2) const
{
int local;
if (cond1) {
local = 1;
} else {
local = 2;
}
if (not cond2) {
local = 3;
} else {
local = 4;
}
}
test.cpp
就是簡單的使用這個 library,會變 compile 成名叫 test-all
的 binary執行程式並收集結果
在 compile 並執行程式後,會發現所有的*.o
旁邊又多了一個 *.gcda
檔案,這些檔案就是記錄剛剛的執行有跑過哪些地方,用來和 gcno 檔做對照用的產生報表
lcov 要用 apt 另外安裝apt-get install lcov
先用 lcov 指定我們 CMakeFiles 資料夾 (我們的 *.o
檔都在裡面),產生 cov.info 檔,裡面會有分析後的統計資料lcov -c -d CMakeFiles -o cov.info
再來用與 lcov 一起安裝的另一個程式 genhtml
來產生報表網頁genhtml cov.info -o report
接著用瀏覽器打開 report 資料夾下的 index.html 就可以看到結合原始碼的結果了100% coverage 就完美了嗎?
這次的範例可以看到PrivateFunction
的 coverage 是 100%,但是查看 test.cpp
就可以發現,我們只測試了四種 case 中的其中兩種,所以以 unit testing 的角度來說並不算 cover 了所有測項,但以 coverage 來說已經算是 100% 了,這邊需要特別注意。
留言
張貼留言