檢視原始碼 mix test.coverage (Mix v1.16.2)
從匯出的測試覆蓋率產生報告。
在此模組文件中,我們將說明 Elixir 中預設的測試覆蓋率運作方式,並探討如何匯出覆蓋率結果,以從多個測試執行中產生群組報告。
程式碼行覆蓋率
Elixir 使用 Erlang 的 :cover
作為其預設的測試覆蓋率。Erlang 覆蓋率是透過追蹤可執行程式碼行來完成的。這表示空白行、程式碼註解、函式簽章和模式不一定可執行,因此不會在覆蓋率報告中追蹤。巨集中的程式碼通常也會在編譯時執行,因此可能不會被覆蓋。類似地,Elixir AST 文字(例如原子)也不是可執行的。
我們來看一個範例
if some_condition? do
do_this()
else
do_that()
end
在上面的範例中,如果你的測試執行 some_condition? == true
和 some_condition? == false
,所有分支都會被覆蓋,因為它們都有可執行程式碼。然而,以下程式碼
if some_condition? do
do_this()
else
:default
end
永遠不會標記 :default
分支為已覆蓋,因為 else
分支中沒有可執行程式碼。不過,請注意,這個問題不會發生在 case
或 cond
上,因為 Elixir 能夠在這種特殊情況下將子句運算子 ->
標記為可執行
case some_condition? do
true ->
do_this()
false ->
:default
end
如果以上程式碼使用這兩個條件進行測試,你應該會看到兩個分支的項目都標記為已覆蓋。
最後,值得討論的是,程式碼行覆蓋率本身有其限制。例如,以下程式碼
do_this() || do_that()
行覆蓋率無法表達 do_this()
和 do_that()
都已執行的狀況,因為只要 do_this()
一執行,整行就已覆蓋。其他技術,例如分支覆蓋率,可以幫助找出這些情況,但目前預設的覆蓋率工具不支援這些技術。
整體而言,程式碼覆蓋率對於找出程式碼中的缺陷(例如尚未覆蓋到的函式)來說是一個很好的工具,但它也可能讓團隊產生一種虛假的安全感,因為即使使用最進階的覆蓋率技術,100% 的覆蓋率也永遠不代表所有不同的執行流程都已斷言。您和您的團隊必須自行決定要多重視覆蓋率。
匯出覆蓋率
當您需要將多個測試執行中的覆蓋率分組時,可以使用此任務。我們來看一些範例。
範例:彙總分割的執行
如果您將測試分割成多個執行,您可以統一報告,如下所示
$ MIX_TEST_PARTITION=1 mix test --partitions 2 --cover
$ MIX_TEST_PARTITION=2 mix test --partitions 2 --cover
$ mix test.coverage
這是因為 --partitions
選項會自動匯出覆蓋率結果。
範例:彙總所有 umbrella 子項目的覆蓋率報告
如果您在 umbrella 中執行 mix test.coverage
,它會自動從所有 umbrella 子項目收集匯出的覆蓋率結果,只要覆蓋率結果已匯出,如下所示
# from the umbrella root
$ mix test --cover --export-coverage default
$ mix test.coverage
當然,如果您實際上想要分割測試,您也可以執行
# from the umbrella root
$ MIX_TEST_PARTITION=1 mix test --partitions 2 --cover
$ MIX_TEST_PARTITION=2 mix test --partitions 2 --cover
$ mix test.coverage
另一方面,如果您想要分割測試,但要產生每個應用程式的報告,您可以執行
# from the umbrella root
$ MIX_TEST_PARTITION=1 mix test --partitions 2 --cover
$ MIX_TEST_PARTITION=2 mix test --partitions 2 --cover
$ mix cmd mix test.coverage
從 umbrella 根目錄執行 test.coverage
時,它會使用 umbrella 根目錄中的 :test_coverage
組態。
最後,請注意,涵蓋範圍本身並未跨專案進行測量。例如,如果專案 B 取決於 A,且 A 中有僅從專案 B 執行的程式碼,這些程式碼行不會標記為已涵蓋,這很重要,因為這些專案應獨立開發和測試。
其他情境
在其他情境中,您可能想要匯出涵蓋範圍。例如,您可能已將測試套件分成兩個部分,一個用於單元測試,另一個用於整合測試。在這種情境中,您可以明確使用 --export-coverage
命令列選項,或在 mix.exs
檔案中的 :test_coverage
下使用 :export
選項。