測試涵蓋範圍

提振精神

軟體測試是協助團隊持續推送優質程式碼的常見做法。以變化版本測試軟體行為、擷取及防止功能或其他所需屬性出現迴歸問題,並協助擴充工程程序。

評估原始碼行涵蓋率的測試涵蓋率,有助於工程師找出測試解決方案的缺口。您可以使用測試涵蓋率做為指標,促進更優質軟體和更安全的開發做法。持續評估測試涵蓋範圍,有助於工程師維持高品質標準。

測試涵蓋範圍無法保證沒有錯誤的程式碼。測試應與模糊測試、靜態和動態分析等其他工具搭配使用。

絕對測試涵蓋範圍

絕對測試涵蓋範圍是整個測試組合涵蓋的原始碼所有行。Fuchsia 的持續整合 (CI) 基礎架構產生絕對涵蓋範圍報表,並持續更新這些資料。涵蓋率報表通常最多只會顯示數小時。

絕對涵蓋率資訊主頁

您可以前往這裡查看最新的絕對涵蓋率報表。 這個資訊主頁會在所有測試過程中發現的程式碼,以樹狀結構形式顯示這些程式碼的樹狀結構,做為來源樹狀結構的子集。您可以按照目錄結構瀏覽樹狀結構,並查看目錄的總涵蓋範圍指標,或檔案的個別行涵蓋率資訊。

此外,Google 內部程式碼搜尋也能使用涵蓋範圍資訊做為圖層。

涵蓋率資訊主頁螢幕截圖

測試涵蓋範圍增量

Gerrit 程式碼審查網頁版 UI 進行變更的情況下,系統會顯示增量測試涵蓋範圍。「增量涵蓋範圍」是指特定變更的情境中,哪些修改後的行會受測試涵蓋,哪些修改行不在測試範圍內。

增量測試涵蓋範圍是由 Fuchsia 的修訂佇列 (CQ) 基礎架構收集而來。將變更傳送至 CQ (Commit-Queue+1) 時,可以按一下「Checks」分頁標籤,然後點選三點圖示選單下方的「Show additional Results」,然後在篩選器文字方塊中輸入「fuchsia-coverage」,以找出負責收集增量涵蓋範圍以在 Gerrit 中顯示的嘗試工作。這個嘗試工作完成後,修補程式集應具有絕對涵蓋率 (|Cov.|) 以及增量涵蓋率 (Δ)

針對會影響專案的變更,維持高成效的逐步測試涵蓋範圍,有助於持續維持高測試涵蓋範圍。尤其要避免在專案中導入新的未測試程式碼。變更作者可以檢視變更的相關涵蓋範圍資訊,確保其測試涵蓋範圍充足。程式碼審查人員可以檢視變更的漸進式測試涵蓋範圍資訊,並要求作者補足任何認為重要的測試落差。

顯示涵蓋率統計資料的 Gerrit 螢幕截圖

顯示線條覆蓋範圍的 Gerrit 螢幕截圖

涵蓋範圍導向的開發工作流程

你可以在瀏覽器或 VS Code 中查看當地編輯內容的涵蓋範圍。 您可以運用這個做法,建立涵蓋率導向的開發工作流程。

準備測試環境

首先,將版本設定為使用涵蓋率變數,並加入將用來示範工作流程的範例。

C++

fx set core.x64 --variant coverage --with examples/hello_world
fx build

Rust

fx set core.x64 --variant coverage-rust --with examples/hello_world
fx build

接著我們要啟動模擬器 (做為目標裝置),然後啟動更新伺服器,這個步驟會使用兩個終端機。如果您已經有執行的目標裝置 (無論是模擬器或實際硬體),可以略過這個步驟。

請在第一個終端機中執行下列操作:

fx qemu -kN

接著,我們來啟動您要用來發布測試套件更新的套件伺服器,這項程序將在背景中執行。如果您已有執行中的套件伺服器,可以略過這個步驟。

請在第二個終端機中執行下列操作:

fx serve

在瀏覽器中查看涵蓋率

在這個工作流程中,我們會執行測試並產生涵蓋率報表,以便在瀏覽器中查看。

執行測試並匯出涵蓋率 HTML 報表

我們的測試並產生 HTML 報告。

C++

fx coverage --html-output-dir $HOME/fx_coverage hello-world-cpp-unittests

Rust

fx coverage --html-output-dir $HOME/fx_coverage hello-world-rust-tests

在瀏覽器中查看涵蓋範圍摘要

使用瀏覽器開啟 $HOME/fx_coverage/index.html。您應該會看到涵蓋率摘要頁面。

涵蓋範圍報表螢幕截圖

點選任一檔案,即可顯示該檔案的換行範圍。「計數」欄會顯示某行在測試中的造訪次數 (1 或以上)。「Count」(計數) 的值沒有 0,即未涵蓋線條。

在 VS Code 中查看涵蓋率

請先準備好測試環境,再開始進行這個部分。

  1. 從 Visual Studio Marketplace 安裝 coverage-gutters 擴充功能。
  2. 將下列屬性新增至 settings.json,即可設定涵蓋率溝槽。
{
    "coverage-gutters.coverageBaseDir": ".",
    "coverage-gutters.showLineCoverage": true,
    "coverage-gutters.coverageFileNames": [ "lcov.info" ]
}

執行測試並查看涵蓋率

讓我們執行測試並匯出 LCOV 檔案,VS Code 將會用來顯示涵蓋範圍。

C++

fx coverage --lcov-output-path $FUCHSIA_DIR/lcov.info hello-world-cpp-unittests

Rust

fx coverage --lcov-output-path $FUCHSIA_DIR/lcov.info hello-world-rust-tests

在 VS Code 中查看涵蓋率

  1. 找出你要查看其涵蓋範圍的檔案。
  2. 在檔案的編輯區域上按一下滑鼠右鍵,然後選取「涵蓋率溝槽:顯示涵蓋率」。
  3. 覆蓋的線條呈現綠色,而未覆蓋的線條則以紅色顯示。
  4. 您可以重新匯出 LCOV 並重做步驟 2,以查看更新後的涵蓋率 (基於某些原因,「手錶」無法正常運作)。

多媒體涵蓋率

VS 程式碼涵蓋率

變更項目後重新執行測試

最後,您可以使用這個指令監控檔案系統的變更,並在您儲存程式碼時重新執行測試。

C++

fx -i coverage --lcov-output-path $FUCHSIA_DIR/lcov.info hello-world-cpp-unittests

Rust

fx -i coverage --lcov-output-path $FUCHSIA_DIR/lcov.info hello-world-rust-tests

端對端 (E2E) 測試排除

只有單元測試和密封整合測試會被視為可靠的測試涵蓋範圍來源。我們不會收集或提出 E2E 測試的測試涵蓋範圍。

E2E 測試是涵蓋整體產品的大型系統測試,並不需要涵蓋原始碼明確定義的部分。舉例來說,在 Fuchsia 的 E2E 測試中,系統常會在模擬器中啟動系統、與其互動,並預期特定行為。

原因

因為 E2E 測試的是整個系統體系:

  • 我們發現在執行期間經常觸發不同的程式碼路徑,導致涵蓋率結果不穩定。
  • 這類架構經常在涵蓋率建構工具時逾時,導致建構工具不穩定。E2E 測試的執行速度遠低於單元測試和小型整合測試,通常需要幾分鐘才能完成。而且在涵蓋範圍建構工具的執行速度會變慢,這是因為涵蓋率增加而降低效能。

方式

系統會針對 core 等頂層建構機器人套件提供對應的 core_no_e2e,因此收集涵蓋率的機器人可以使用 no_e2e 套件,避免建構及執行任何 E2E 測試。

目前沒有可靠的方法可識別所有樹狀結構內 E2E 測試。no_e2e 套裝組合是以 Proxy 的形式運作,也就是透過 GN 的 assert_no_deps,在其遞迴依附元件中不含任何已知的 e2e 測試程式庫。E2E 測試程式庫清單是手動收錄及維護,假設其變更頻率極低:

e2e_test_libs = [
  "//sdk/testing/sl4f/client",
  "//third_party/mobly($host_toolchain)",
  "//src/testing/end_to_end/honeydew($host_toolchain)",
]
if (is_linux) {
  e2e_test_libs += [ "//tools/emulator($host_toolchain)" ]
}

限制

目前,系統只會在以下情況下收集測試涵蓋範圍:

  • 程式碼是以 C、C++ 或 Rust 編寫而成。
  • 程式碼會在 Fuchsia 的使用者模式中執行,或是在主機上執行。尚不支援核心涵蓋率 (追蹤錯誤)。
  • 測試會在 qemu 上執行。尚不支援硬體測試。
  • 測試會在 core 產品設定中執行。
  • 不支援端對端 (e2e) 測試。

最後請注意,e2e 測試在整個系統中執行許多程式碼,但執行方式在執行作業之間出現不一致 (或「不穩定」) 的情形。如要擴大程式碼的測試涵蓋範圍,實際上可以使用單元測試和整合測試進行上述操作。

實驗功能

根據預設,增量涵蓋範圍只會在 core.x64 中收集。如要收集 core.x64core.arm64 的變更合併涵蓋範圍,請按照下列步驟操作:

  1. 在 Gerrit 中,前往「Checks」(檢查) 分頁。
  2. 按下 [選擇嘗試工作]。
  3. 新增 fuchsia-coverage-x64-arm64

在 Gerrit 中手動選擇 x64-arm64 覆蓋範圍

畫面上會顯示勾號。工作從待處理狀態變為待處理後,重新整理 Gerrit 即可查看涵蓋率結果。

另請參閱:問題 91893:Gerrit 只收集 x64 的涵蓋範圍增量

即將推出的新功能

我們正在開發以下其他用途的支援功能:

  • 核心程式碼涵蓋率。
  • core 以外的產品設定涵蓋範圍,例如 bringupworkstation_eng
  • 指定硬體目標的涵蓋範圍,從並非在 Qemu 執行的測試中收集。

疑難排解

不支援的設定 / 語言 / 執行階段

如果未顯示程式碼的絕對或增量資訊,請先詳閱限制,並確認程式碼預期能獲得涵蓋率支援。

為協助您進行疑難排解,請檢查您是否遺漏涵蓋範圍 (行應有涵蓋率但顯示為不在涵蓋範圍內) 或完全沒有任何涵蓋範圍資訊 (檔案完全不會出現在涵蓋率報表中,或者系統是否未註解說明項目是否涵蓋項目)。

缺少涵蓋率表示程式碼是以檢測設備建構而成,但實際上並未包含在執行的測試中。如果沒有任何涵蓋範圍資訊可能表示程式碼並非以涵蓋率建構,或者測試不在涵蓋率範圍內 (詳情請參閱下文)。

報表過時 / 延遲

絕對涵蓋率報表會在合併程式碼後產生,可能需要數小時才能完整編譯。資訊主頁會顯示所產生報表的修訂版本雜湊值。如果資訊主頁上未顯示預期結果,請確認資料是在最近產生的任何變更,且可能影響涵蓋範圍。如果資料已過期,請稍後再回來重新整理頁面。

涵蓋範圍報表是由高階主管產生請確認您查看的是已傳送至 CQ 的修補程式集。您可以按一下「Show 實驗 tryjobs」(顯示實驗效果),查看名為 fuchsia-coverage 的 tryjob。如果 tryjob 工作仍在執行中,請稍後再回來重新整理頁面。

確保測試可執行

如果程式碼缺少預期的涵蓋率,請選擇應該涵蓋程式碼的測試,並確保該測試執行在涵蓋率嘗試工作中。

  1. 在 Gerrit 中找到 tryjob,或是在 CI 資訊主頁中尋找最近的 fuchsia-coverage 執行作業。
  2. 在「Overview」分頁中找出「collect build」步驟並展開該步驟,即可找到顯示不同設定涵蓋範圍和測試執行作業的頁面連結。
  3. 每個頁面都應有「測試結果」分頁,當中顯示已執行的所有測試。請確保您預期的測試可以執行,且建議通過測試。

如果測試並未依預期執行任何涵蓋範圍嘗試工作,原因可能就是僅在 CI/CQ 目前未涵蓋的設定中執行。另一個原因是,測試已明確選擇納入涵蓋率變化版本。舉例來說,參照測試的 BUILD.gn 檔案可能如下所示:

fuchsia_test_package("foo_test") {
  test_components = [ ":test" ]
  deps = [ ":foo" ]

  # TODO(https://fxbug.dev/42074368): This test is intentionally disabled on coverage.
  if (is_coverage) {
    test_specs = {
      environments = [
        {
          dimensions = emu_env.dimensions
          tags = [ "disabled" ]
        },
      ]
    }
  }
}

請尋找背景資訊,瞭解測試停止在涵蓋範圍內並進行調查的原因。

如要查看測試因未設為在 CQ 上執行,而未顯示涵蓋率的疑難排解範例,請參閱這篇文章

只測試失敗或損壞在涵蓋範圍內的測試

就上述情況而言,涵蓋率範例下可能較不穩定。在執行階段收集涵蓋範圍的額外負荷會降低效能,進而影響時間,通常是導致額外不穩定的原因。

另一個原因可能是測試期間沒有在一般測試執行時發生逾時的情況。實驗結果顯示,由於收集執行階段設定檔會增加負擔,因此平均測試在涵蓋率變化版本中的執行速度平均會降低 2.3 倍。為瞭解決這個問題,測試執行元件會在執行涵蓋率版本時,為每次測試提供較長的逾時時間。然而,測試可能仍會有自己的內部作業逾時,這可能會受到影響。

原則上,我們不應在測試中設定逾時。在測試中等待非同步作業時,最好等待無限期,讓測試執行元件的整體逾時時間過期。

最後,涵蓋率變化版本元件可能會使用 fuchsia.debug.DebugData 通訊協定。這可能會幹擾到測試,確切瞭解元件所使用的功能為何。請參閱:

如要立即解決測試問題,可立即停用涵蓋範圍內的測試 (請參閱上述的 GN 程式碼片段),但這樣就不必立即從測試收集涵蓋範圍資訊。最佳做法是對涵蓋率處理相同,就像在其他地方處理火花一樣,主要是為了修正不穩定。

另請參閱:不穩定測試政策

格里特境內未看到預計涵蓋率

如果沒有看到特定行的涵蓋率,但您確信執行中的測試應涵蓋這些行,請嘗試按下「選擇試用工作」、找出 fuchsia-coverage 並新增,再次收集這些行的涵蓋範圍。

新增沙發背蓋的 Gerrit 螢幕截圖

如果 fuchsia-coverage 完成 (變為綠色),且您看到不同的線條覆蓋結果結果,表示下列其中一種情況:

  1. 測試在不同執行作業之間以不一致的方式執行受測試的程式碼。這通常也會產生不穩定的測試結果,通常這是測試行為或測試中的程式碼發生問題。
  2. 系統產生及收集涵蓋範圍時,會導致結果不一致。請回報錯誤。

測試涵蓋範圍的運作方式

Fuchsia 的程式碼涵蓋率建構、測試執行階段支援和處理工具採用 LLVM 原始碼涵蓋率。Fuchsia 平台是由編譯器-rt 設定檔執行階段提供支援。

選取 "coverage" 建構變數時,就會啟用設定檔檢測功能。然後,編譯器會產生計數器,將每個計數器都對應至程式碼控制流程中的分支版本,並針對分支版本項目發出指令,以增加相關聯的計數器。此外,設定檔檢測執行階段程式庫會連結至執行檔。

詳情請參閱 LLVM 程式碼涵蓋率對應格式

請注意,這項檢測作業會導致二進位檔大小增加、記憶體用量增加,並縮短測試執行時間。已採取某些步驟減緩這個目標:

  • 設定檔變化版本中的測試適用較長的逾時時間。
  • 設定檔變化版本中的測試會根據一些最佳化項目編譯。
  • 目前在模擬器中執行,而模擬器的儲存空間較少。
  • 如果是漸進式涵蓋率,只有受到該變更影響的來源才會進行檢測。

Fuchsia 上的設定檔執行階段程式庫會將設定檔資料儲存在 VMO 中,並使用 fuchsia.debug.DebugData 通訊協定將控制代碼發布至 VMO。您可以在執行階段使用元件架構進行測試,並由 Test Runner Framework 的裝置端控制器 (測試管理員) 代管。

系統會在測試領域終止後,以及當中代管的所有元件收集設定檔。接著,系統會將設定檔處理為測試的單一摘要。這個重要的最佳化可以大幅縮減設定檔總大小。接著,系統會將最佳化的設定檔傳送至主機端測試控制器。

主機會使用 covargs 工具,這項工具本身使用 llvm-profdatallvm-cov 工具,將原始設定檔轉換為摘要格式,並產生測試涵蓋範圍報表。此外,covargs 會將資料轉換為 protobuf 格式,這種格式可做為與不同資訊主頁的交互格式使用。

發展藍圖

進行中的工作:

  • 提高涵蓋率執行階段的效能和穩定性。
  • 針對 ZBI 測試的原始碼涵蓋率提供核心支援。
  • 自訂涵蓋範圍資訊主頁和快訊:為團隊建立資訊主頁。
  • 本機工作流程:在本機執行測試、在本機產生涵蓋率報表。
  • IDE 整合:查看 VS Code 中的涵蓋率層。

近期工作:

  • 樹狀結構外支援:Fuksia CI/CQ 以外的涵蓋範圍。

其他資訊