2010-08-24 37 views
36

我使用gcov來衡量我的C++代碼中的覆蓋率。我希望達到100%的覆蓋率,但受到以下事實的阻礙:理論上有一些代碼行是不可觸發的(這些方法需要實現,但從未被調用,默認分支爲switch聲明,等等。)。這些分支中的每一個都包含assert(false);聲明,但gcov仍將其標記爲未命中。如何告訴gcov忽略C++代碼的不可擊中行?

我希望能夠告訴gcov忽略這些分支。有什麼辦法可以給gcov這些信息 - 通過註釋源代碼或其他機制?

+0

是什麼讓你如此肯定行是unhittable?如果是因爲你沒有能夠擊中它們,那麼你就是在試圖找出代碼覆蓋面。 – doron 2010-08-24 09:48:06

+2

@ deus-ex-machina399:不,這不是因爲我沒能打到他們。這是由於對代碼的理解和分析。當然,我可能是錯的,但我沒有使用代碼覆蓋率分析來驗證我對源代碼的理解。我使用代碼覆蓋率分析來驗證我的測試套件的質量。 – jchl 2010-08-24 09:53:39

+1

@doron,應該是unhittable的代碼的一個示例是測試基礎結構中的失敗路徑。當然,你可能沒有這樣的路徑,但我擁有它們。 – 2015-04-06 02:13:52

回答

35

請使用lcov。它隱藏的gcov的複雜性,會產生很好的輸出,允許每個測試詳細的輸出,具有易於文件濾波和 - TA-TAA - 線標記爲已審查行:

從geninfo(1):

以下標記由geninfo確認:

  • LCOV_EXCL_LINE含有此標記
    • 線將被排除。
  • LCOV_EXCL_START
    • 標記排除的部分的開頭。當前行是本節的一部分。
  • LCOV_EXCL_STOP
    • 標記排除的部分的端部。當前行不是本節的一部分。
+0

有趣的是,我沒有聽說過lcov。感謝您的推薦! – jchl 2011-01-21 09:01:35

+0

終於到處去測試這個......並且在升級到lcov> = 1.8版本之後,它起到了魅力。謝謝! – jchl 2012-01-05 16:58:34

+14

我不喜歡「使用其他工具」形式的答案。我其實想知道如何讓gcov忽略行,並且沒有切換到lcov的選項。所以這不能回答這個問題。 – 2014-01-27 02:07:58

0

我不相信這是可能的。 Gcov依靠gcc生成額外的代碼來產生覆蓋率輸出。 GCov本身只是解析數據。這意味着Gcov無法比gcc更好地分析代碼(並且我假設你使用了-Wall並刪除了被報告爲無法訪問的代碼)。

請記住,可以從任何地方調用可重定位函數,甚至可能是外部dll或可執行文件,因此編譯器無法知道哪些可重定位函數不會被調用或者這些函數可能具有哪些輸入。

您可能需要使用某些facy靜態分析工具來獲取所需的信息。

1

你可以介紹一下相關函數的單元測試嗎?它只存在於直接攻擊理論上不可訪問的代碼路徑時關閉gcov?既然他們是單元測試,他們或許可以忽略這種情況的「不可能性」。他們可以調用從不被調用的函數,傳遞無效的枚舉值來捕獲缺省分支等。

然後,或者只在您使用NDEBUG編譯的代碼版本上運行這些測試,否則在測試的線束中運行它們無論您的測試框架支持,斷言都會被觸發。

我覺得它有點奇怪,但規範說,代碼必須在那裏,而不是包含代碼功能要求的規範。尤其是,這意味着您的測試不會測試這些需求,這與保持需求功能的任何原因一樣是一個很好的理由。就我個人而言,我想修改規範說:「如果用無效的枚舉值調用,函數將失敗assert。在釋放模式下,調用者不應使用無效的枚舉值調用該函數」。或者這樣。

大概它現在說的是,沿着「所有開關語句都必須有一個默認情況」。但這意味着編碼標準通過引入死代碼來干擾可觀察行爲(至少在gcov下可觀察到)。編碼標準不應該這樣做,所以如果可能的話,功能規範應該考慮編碼標準。

如果沒有這樣做,你可能會在#if !GCOV_BUILD中包裝不可用的代碼,併爲gcov的好處做一個單獨的構建。這個構建將會失敗一些要求,但是有條件的分析代碼是正確的,它會讓你有信心讓測試套件測試其他的一切。

編輯:你說你正在使用一個狡猾的代碼生成器,但你也通過註釋源代碼要求解決方案。如果您要更改源代碼,您是否可以在很多情況下刪除死代碼?不是說改變生成的來源是理想的,但需要...

+0

這不是說「功能」說功能必須在那裏。我們有一個代碼生成器,可以爲這些功能生成原型,即使它們沒有被使用。 (修復代碼生成器將是一個更好的選擇,但不幸的是,這不在我的控制之下。)另一種情況下,它有時會出現在你實現接口的地方(即從具有純虛擬函數的類派生),但僅僅使用該界面的一部分。 – jchl 2010-08-24 14:02:26

+0

讓單元測試直接調用函數並不是一個壞主意,儘管必須在NDEBUG構建上運行測試會很痛苦(目前我們的單元測試都是在調試版本上運行)。這聽起來像更多的工作,而不是價值。我可以擺脫斷言,但我喜歡他們爲了文檔的目的。我可以用拋出一個特殊的異常來替換它們,除非在單元測試期間,這個異常從來沒有被捕獲過....這不是一個壞主意。 – jchl 2010-08-24 14:06:27

+0

@jchl:「你正在實現一個接口(即從具有純虛擬函數的類派生而來),但只使用該接口的一部分。」 - 有點。但是,如果我爲這個類編寫全面的測試,我仍然會讓這個類定義它們的作用,並從測試中調用未使用的函數,以確保它們能夠做到。如果我沒有編寫全面的測試,我不在乎我是否有代碼覆蓋;-) – 2010-08-24 15:25:36