檢視原始碼 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? == truesome_condition? == false,所有分支都會被覆蓋,因為它們都有可執行程式碼。然而,以下程式碼

if some_condition? do
  do_this()
else
  :default
end

永遠不會標記 :default 分支為已覆蓋,因為 else 分支中沒有可執行程式碼。不過,請注意,這個問題不會發生在 casecond 上,因為 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 選項。