提振精神
軟體測試是協助團隊持續推送優質程式碼的常見做法。以變化版本測試軟體行為、擷取及防止功能或其他所需屬性出現迴歸問題,並協助擴充工程程序。
評估原始碼行涵蓋率的測試涵蓋率,有助於工程師找出測試解決方案的缺口。您可以使用測試涵蓋率做為指標,促進更優質軟體和更安全的開發做法。持續評估測試涵蓋範圍,有助於工程師維持高品質標準。
測試涵蓋範圍無法保證沒有錯誤的程式碼。測試應與模糊測試、靜態和動態分析等其他工具搭配使用。
絕對測試涵蓋範圍
絕對測試涵蓋範圍是整個測試組合涵蓋的原始碼所有行。Fuchsia 的持續整合 (CI) 基礎架構產生絕對涵蓋範圍報表,並持續更新這些資料。涵蓋率報表通常最多只會顯示數小時。
絕對涵蓋率資訊主頁
您可以前往這裡查看最新的絕對涵蓋率報表。 這個資訊主頁會在所有測試過程中發現的程式碼,以樹狀結構形式顯示這些程式碼的樹狀結構,做為來源樹狀結構的子集。您可以按照目錄結構瀏覽樹狀結構,並查看目錄的總涵蓋範圍指標,或檔案的個別行涵蓋率資訊。
此外,Google 內部程式碼搜尋也能使用涵蓋範圍資訊做為圖層。
測試涵蓋範圍增量
在 Gerrit 程式碼審查網頁版 UI 進行變更的情況下,系統會顯示增量測試涵蓋範圍。「增量涵蓋範圍」是指特定變更的情境中,哪些修改後的行會受測試涵蓋,哪些修改行不在測試範圍內。
增量測試涵蓋範圍是由 Fuchsia 的修訂佇列 (CQ) 基礎架構收集而來。將變更傳送至 CQ (Commit-Queue+1) 時,可以按一下「Checks」分頁標籤,然後點選三點圖示選單下方的「Show additional Results」,然後在篩選器文字方塊中輸入「fuchsia-coverage」,以找出負責收集增量涵蓋範圍以在 Gerrit 中顯示的嘗試工作。這個嘗試工作完成後,修補程式集應具有絕對涵蓋率 (|Cov.|) 以及增量涵蓋率 (Δ)
針對會影響專案的變更,維持高成效的逐步測試涵蓋範圍,有助於持續維持高測試涵蓋範圍。尤其要避免在專案中導入新的未測試程式碼。變更作者可以檢視變更的相關涵蓋範圍資訊,確保其測試涵蓋範圍充足。程式碼審查人員可以檢視變更的漸進式測試涵蓋範圍資訊,並要求作者補足任何認為重要的測試落差。
涵蓋範圍導向的開發工作流程
你可以在瀏覽器或 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 中查看涵蓋率
請先準備好測試環境,再開始進行這個部分。
- 從 Visual Studio Marketplace 安裝 coverage-gutters 擴充功能。
- 將下列屬性新增至
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 中查看涵蓋率
- 找出你要查看其涵蓋範圍的檔案。
- 在檔案的編輯區域上按一下滑鼠右鍵,然後選取「涵蓋率溝槽:顯示涵蓋率」。
- 覆蓋的線條呈現綠色,而未覆蓋的線條則以紅色顯示。
- 您可以重新匯出 LCOV 並重做步驟 2,以查看更新後的涵蓋率 (基於某些原因,「手錶」無法正常運作)。
變更項目後重新執行測試
最後,您可以使用這個指令監控檔案系統的變更,並在您儲存程式碼時重新執行測試。
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.x64
和 core.arm64
的變更合併涵蓋範圍,請按照下列步驟操作:
- 在 Gerrit 中,前往「Checks」(檢查) 分頁。
- 按下 [選擇嘗試工作]。
- 新增
fuchsia-coverage-x64-arm64
。
畫面上會顯示勾號。工作從待處理狀態變為待處理後,重新整理 Gerrit 即可查看涵蓋率結果。
另請參閱:問題 91893:Gerrit 只收集 x64 的涵蓋範圍增量
即將推出的新功能
我們正在開發以下其他用途的支援功能:
- 核心程式碼涵蓋率。
core
以外的產品設定涵蓋範圍,例如bringup
或workstation_eng
。- 指定硬體目標的涵蓋範圍,從並非在 Qemu 執行的測試中收集。
疑難排解
不支援的設定 / 語言 / 執行階段
如果未顯示程式碼的絕對或增量資訊,請先詳閱限制,並確認程式碼預期能獲得涵蓋率支援。
為協助您進行疑難排解,請檢查您是否遺漏涵蓋範圍 (行應有涵蓋率但顯示為不在涵蓋範圍內) 或完全沒有任何涵蓋範圍資訊 (檔案完全不會出現在涵蓋率報表中,或者系統是否未註解說明項目是否涵蓋項目)。
缺少涵蓋率表示程式碼是以檢測設備建構而成,但實際上並未包含在執行的測試中。如果沒有任何涵蓋範圍資訊可能表示程式碼並非以涵蓋率建構,或者測試不在涵蓋率範圍內 (詳情請參閱下文)。
報表過時 / 延遲
絕對涵蓋率報表會在合併程式碼後產生,可能需要數小時才能完整編譯。資訊主頁會顯示所產生報表的修訂版本雜湊值。如果資訊主頁上未顯示預期結果,請確認資料是在最近產生的任何變更,且可能影響涵蓋範圍。如果資料已過期,請稍後再回來重新整理頁面。
涵蓋範圍報表是由高階主管產生請確認您查看的是已傳送至 CQ 的修補程式集。您可以按一下「Show 實驗 tryjobs」(顯示實驗效果),查看名為 fuchsia-coverage
的 tryjob。如果 tryjob 工作仍在執行中,請稍後再回來重新整理頁面。
確保測試可執行
如果程式碼缺少預期的涵蓋率,請選擇應該涵蓋程式碼的測試,並確保該測試執行在涵蓋率嘗試工作中。
- 在 Gerrit 中找到 tryjob,或是在 CI 資訊主頁中尋找最近的
fuchsia-coverage
執行作業。 - 在「Overview」分頁中找出「collect build」步驟並展開該步驟,即可找到顯示不同設定涵蓋範圍和測試執行作業的頁面連結。
- 每個頁面都應有「測試結果」分頁,當中顯示已執行的所有測試。請確保您預期的測試可以執行,且建議通過測試。
如果測試並未依預期執行任何涵蓋範圍嘗試工作,原因可能就是僅在 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
並新增,再次收集這些行的涵蓋範圍。
如果 fuchsia-coverage
完成 (變為綠色),且您看到不同的線條覆蓋結果結果,表示下列其中一種情況:
- 測試在不同執行作業之間以不一致的方式執行受測試的程式碼。這通常也會產生不穩定的測試結果,通常這是測試行為或測試中的程式碼發生問題。
- 系統產生及收集涵蓋範圍時,會導致結果不一致。請回報錯誤。
測試涵蓋範圍的運作方式
Fuchsia 的程式碼涵蓋率建構、測試執行階段支援和處理工具採用 LLVM 原始碼涵蓋率。Fuchsia 平台是由編譯器-rt 設定檔執行階段提供支援。
選取 "coverage"
建構變數時,就會啟用設定檔檢測功能。然後,編譯器會產生計數器,將每個計數器都對應至程式碼控制流程中的分支版本,並針對分支版本項目發出指令,以增加相關聯的計數器。此外,設定檔檢測執行階段程式庫會連結至執行檔。
詳情請參閱 LLVM 程式碼涵蓋率對應格式。
請注意,這項檢測作業會導致二進位檔大小增加、記憶體用量增加,並縮短測試執行時間。已採取某些步驟減緩這個目標:
- 設定檔變化版本中的測試適用較長的逾時時間。
- 設定檔變化版本中的測試會根據一些最佳化項目編譯。
- 目前在模擬器中執行,而模擬器的儲存空間較少。
- 如果是漸進式涵蓋率,只有受到該變更影響的來源才會進行檢測。
Fuchsia 上的設定檔執行階段程式庫會將設定檔資料儲存在 VMO 中,並使用 fuchsia.debug.DebugData
通訊協定將控制代碼發布至 VMO。您可以在執行階段使用元件架構進行測試,並由 Test Runner Framework 的裝置端控制器 (測試管理員) 代管。
系統會在測試領域終止後,以及當中代管的所有元件收集設定檔。接著,系統會將設定檔處理為測試的單一摘要。這個重要的最佳化可以大幅縮減設定檔總大小。接著,系統會將最佳化的設定檔傳送至主機端測試控制器。
主機會使用 covargs
工具,這項工具本身使用 llvm-profdata
和 llvm-cov
工具,將原始設定檔轉換為摘要格式,並產生測試涵蓋範圍報表。此外,covargs
會將資料轉換為 protobuf 格式,這種格式可做為與不同資訊主頁的交互格式使用。
發展藍圖
進行中的工作:
- 提高涵蓋率執行階段的效能和穩定性。
- 針對 ZBI 測試的原始碼涵蓋率提供核心支援。
- 自訂涵蓋範圍資訊主頁和快訊:為團隊建立資訊主頁。
- 本機工作流程:在本機執行測試、在本機產生涵蓋率報表。
- IDE 整合:查看 VS Code 中的涵蓋率層。
近期工作:
- 樹狀結構外支援:Fuksia CI/CQ 以外的涵蓋範圍。