查看源代码 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
选项会自动导出覆盖率结果。
示例:汇总所有伞形子项目中的覆盖率报告
如果您在伞形项目中运行 mix test.coverage
,它会自动收集所有伞形子项目的导出覆盖率结果 - 只要覆盖率结果已导出,就像这样
# 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
从伞形项目根目录运行 test.coverage
时,它将使用伞形项目根目录中的 :test_coverage
配置。
最后,请注意,覆盖率本身不会跨项目进行衡量。例如,如果项目 B 依赖于 A,并且 A 中的某些代码仅在项目 B 中执行,那么这些行将不会被标记为已覆盖,这一点很重要,因为这些项目应该独立开发和测试。
其他场景
您可能还有其他导出覆盖率的场景。例如,您可能将测试套件分为两个,一个用于单元测试,另一个用于集成测试。在这种情况下,您可以显式使用 --export-coverage
命令行选项,或者使用 mix.exs
文件中 :test_coverage
下的 :export
选项。