如何生成 Rust 代碼覆蓋率
代碼覆蓋率是一個至關重要的度量標準,它可以很好地洞察軟件質量。代碼覆蓋率通常以百分比表示,並提供有關軟件的多少代碼被一組單元測試或測試套件測試。把它想象成一個文本高亮工具,它顯示代碼的哪些部分經過測試,哪些部分可以考慮進行進一步測試,以提高代碼的質量。
更高的代碼覆蓋率增加了對代碼功能的信心,並降低了 bug 的風險。大多數代碼覆蓋工具都可以集成到 CI 管道中,這樣代碼覆蓋就可以隨着代碼的增長而不斷改進。在一些項目中,代碼覆蓋需求包含在合併策略中,以確保軟件質量。由於代碼覆蓋工具還報告了測試套件未測試的代碼區域,因此它有助於確定測試的重點區域。在某些安全至關重要的受監管領域,如汽車、航空航天和醫療保健,就更需要代碼覆蓋信息。
有多種方法可以用來評估測試軟件的代碼覆蓋率,如下所述。
1,語句覆蓋率: 儘管更流行的術語是行覆蓋,但在許多語言中,一行中可能有多條語句,因此純粹主義者更喜歡使用語句覆蓋。如果一條語句在運行測試套件時至少執行一次,則認爲它已被覆蓋。
2,區域覆蓋率: 它是已執行的代碼區域的百分比,代碼區域可以跨越由多個語句組成的多行,例如函數體。
3,分支覆蓋率: 分支覆蓋率是軟件測試中使用的一個度量,用於評估一組測試用例執行了程序控制流中的多少分支或決策點。在代碼覆蓋率分析的上下文中,“分支”通常指的是代碼中的一個決策點,程序可以根據條件 (例如,if 語句或 switch 語句) 採取不同的路徑。
4,MC/DC 覆蓋率: 修改條件 / 決策覆蓋 (Modified Condition/Decision coverage, MC/DC) 是一種用於關鍵安全系統的嚴格的軟件測試技術。它確保代碼中的每個決策都在所有可能的結果下進行了測試,並且決策中的每個條件都可以獨立地影響決策的結果。MC/DC 的優勢在於它的效率。它提供了高水平的故障檢測,同時比完全條件覆蓋所需的測試用例更少。
在這篇文章中,我們將討論如何爲 Rust 應用程序生成代碼覆蓋信息。我們還將討論與支持代碼覆蓋相關的 Rust 編譯器未來版本的當前狀態和特性。Rust 使用 LLVM 作爲編譯後端。相應地,Rust 編譯器利用了 LLVM 提供的一些檢測覆蓋特性。隨着在 LLVM 中添加相應的功能,Rust 中的支持代碼覆蓋的功能有望增長。我們將簡要討論 Rust 編譯器對 LLVM 代碼覆蓋特性的依賴。
在 Rust 中啓用代碼覆蓋
Rust 中的代碼覆蓋率數據可以通過以下兩種方法收集:
1,使用 - Z profile 命令標誌
這使用了與 gcc 兼容的基於 gcov 的覆蓋實現。簡單來說,它可以幫助你收集基於 DebugInfo 的覆蓋率數據。當你想要查看代碼的哪些部分正在執行,哪些部分沒有執行時,這是非常方便的,這就像有一個代碼執行的路線圖。
2. 使用 - C instrument-coverage 命令標誌
此標誌啓用 LLVM 的本機覆蓋檢測,它以其效率和精度而聞名。它提供了高度精確的覆蓋率數據,可以檢查正在執行的代碼的確切部分。這對於識別未被測試的代碼區域非常有用。因此,當你希望使用高度精確的數據來提高測試的健壯性時,可以選擇基於 -C instrument-coverage 的覆蓋工具。
在本文中,我們將詳細討論 -C instrument-coverage 標誌,它更廣泛地用於基於源代碼的代碼覆蓋。
下面的簡單示例說明了這是如何工作的。
pub fn is_even(n: u32) -> bool {
if n % 2 == 0 {
true
} else {
false
}
}
測試代碼如下:
#[test]
pub fn test_even() {
assert_eq!(is_even(2), true);
}
爲了啓用代碼覆蓋,我們在用 Rust 編譯器編譯程序時使用 -C instrument-coverage 標誌。
如果我們使用 Cargo 來構建程序,我們可以通過設置 RUSTFLAGS 環境變量啓用這個標誌,如下所示。
RUSTFLAGS="-Cinstrument-coverage" cargo test
這將產生所謂的 “儀表化” 二進制 / 可執行文件,其中注入了額外的代碼來計算行、區域和分支。
實際上發生的事情是編譯器注入如下所示的計數器增量來跟蹤計數:
pub fn is_even(n: u32) -> bool {
is_even_counter += 1;
if n % 2 == 0 {
is_even_true_branch_counter += 1;
true
} else {
is_even_false_branch_counter += 1;
false
}
}
因此,每當輸入特定的功能 / 區域或分支時,相關的計數器就會增加。所有這些計數器都存儲在程序內存中的特定位置。
除此之外,一個額外的運行時也被注入到二進制文件中,它在程序的整個生命週期中初始化和管理這些計數器 (稱爲 LLVM 分析器運行時)。
pub fn main() {
__initialize_counters();
test_even();
//Other tests….
__write_counter_data_to_file();
}
當程序退出時,來自這些計數器的原始數據被寫入 “profraw” 文件,該文件可用於創建覆蓋率報告。
Rust 中的代碼覆蓋工具
下面是在 Rust 中流行的覆蓋工具:
1,Tarpaulin: Tarpaulin 是一個免費的 Rust 庫,提供源代碼行覆蓋功能。它仍處於開發的早期階段,但它已經被證明是測試 Rust 應用程序的一個好選擇。
2,grcov: grcov 是一個免費的庫,它收集和聚合項目中所有 Rust 文件的代碼覆蓋率信息,在內部使用 llvm-cov 來創建報告。
3,cargo-llvm-cov: 這是 Rust 代碼覆蓋的另一個流行工具。
使用 cargo-tarpaulin
Cargo-tarpaulin 是 Rust 生態系統中收集代碼覆蓋率數據的流行工具,它被設計成與 cargo 構建系統一起使用。下面是一個簡單的例子,告訴你如何使用 cargo-tarpaulin:
# 安裝 cargo-tarpaulin
cargo install cargo-tarpaulin
# 運行 cargo-tarpaulin 收集覆蓋率數據
cargo tarpaulin
結果如下:
INFO cargo_tarpaulin::statemachine::instrumented: For binary: target/debug/deps/code_covrage-4e2873bf50ec5596
INFO cargo_tarpaulin::statemachine::instrumented: Generated: target/tarpaulin/profraws/code_covrage-4e2873bf50ec5596_16540310165768346208_0-50218.profraw
INFO cargo_tarpaulin::statemachine::instrumented: Merging coverage reports
INFO cargo_tarpaulin::statemachine::instrumented: Mapping coverage data to source
INFO cargo_tarpaulin::report: Coverage Results:
|| Uncovered Lines:
|| src/main.rs: 5, 9
|| Tested/Total Lines:
|| src/main.rs: 3/5
||
60.00% coverage, 3/5 lines covered
在這個例子中,cargo-tarpaulin 將在控制檯中自動生成報告,對於更詳細的報告,cargo-tarpaulin 支持多種輸出格式,如 Json、Xml 和 Html。
使用 grcov
Grcov 是一個從測試套件中收集和聚合代碼覆蓋率數據的 Rust 工具。當你想要將代碼覆蓋率報告集成到持續集成管道中時,它特別有用。下面是如何在 Rust 項目中使用 grcov 的一個簡單示例:
# 安裝 grcov
cargo install grcov
# 運行測試
RUSTFLAGS="-Cinstrument-coverage" cargo test
# 生成覆蓋率報告
grcov . -s . --binary-path ./target/debug/ -t html --ignore tests/ -o ./target/debug/coverage/
# 在瀏覽器中打開HTML文件查看報告
open target/debug/coverage/index.html
下圖顯示了一個示例覆蓋率報告。我們可以找到項目中每個 Rust 模塊的覆蓋信息,如行覆蓋、函數覆蓋和分支覆蓋。
使用 cargo-llvm-cov
Cargo-llvm-cov 是一個 Rust 工具,它利用 LLVM 基於源代碼的代碼覆蓋率來生成詳細的覆蓋率報告。下面是一個簡單的例子,說明如何在 Rust 項目中使用 cargo-llvm-cov。
# 安裝 cargo-llvm-cov
cargo install cargo-llvm-cov
# 運行有覆蓋率的測試
cargo llvm-cov
這將在控制檯中生成詳細的覆蓋率報告,結果如下:
Filename Regions Missed Regions Cover Functions Missed Functions Executed Lines Missed Lines Cover Branches Missed Branches Cover
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
../code-covrage/src/main.rs 8 2 75.00% 4 1 75.00% 10 2 80.00% 0 0 -
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL 8 2 75.00% 4 1 75.00% 10 2 80.00% 0 0 -
總結
代碼覆蓋率爲評估和改進源代碼的質量提供了非常有用的信息。Rust 已經爲諸如行覆蓋、函數覆蓋等特性提供了很好的支持。雖然 LLVM 支持分支覆蓋和 MC/DC 覆蓋,但仍有一些功能有待添加。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/VL3R318XNygQjbsDvYonxQ