模块 Coverage

Coverage 为 Ruby 提供覆盖率测量功能。此功能是实验性的,因此这些 API 在未来可能会更改。

警告:目前,仅支持进程全局覆盖率测量。你不能测量每个线程的覆盖率。

用法

  1. require “coverage”

  2. do Coverage.start

  3. require 或加载 Ruby 源文件

  4. Coverage.result 将返回一个哈希,其中包含文件名作为键,覆盖率数组作为值。覆盖率数组给出了解释器对每行代码的执行次数。nil 值表示此行的覆盖率已禁用(如 elseend 行)。

示例

[foo.rb]
s = 0
10.times do |x|
  s += x
end

if s == 45
  p :ok
else
  p :ng
end
[EOF]

require "coverage"
Coverage.start
require "foo.rb"
p Coverage.result  #=> {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}

Coverage

如果在启动覆盖率时未显式指定覆盖率模式,则将运行行覆盖率。它报告每行代码的执行次数。

require "coverage"
Coverage.start(lines: true)
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>{:lines=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}}

行覆盖率结果的值是一个数组,其中包含每行代码的执行次数。此数组中的顺序很重要。例如,此数组中索引为 0 的第一个项目报告在运行覆盖率时此文件的第 1 行执行了多少次(在此示例中为一次)。

nil 值表示此行的覆盖率已禁用(如 elseend 行)。

单次行 Coverage

单次行覆盖率跟踪并报告在运行覆盖率时执行的行。它不会报告一行执行了多少次,仅报告它被执行过。

require "coverage"
Coverage.start(oneshot_lines: true)
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>{:oneshot_lines=>[1, 2, 3, 6, 7]}}

单次行覆盖率结果的值是一个数组,其中包含已执行的行号。

分支 Coverage

分支覆盖率报告每个条件语句中每个分支的执行次数。

require "coverage"
Coverage.start(branches: true)
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>{:branches=>{[:if, 0, 6, 0, 10, 3]=>{[:then, 1, 7, 2, 7, 7]=>1, [:else, 2, 9, 2, 9, 7]=>0}}}}

分支哈希中的每个条目都是一个条件语句,其值是另一个哈希,其中每个条目是该条件语句中的一个分支。这些值是该方法执行的次数,键是关于该分支的标识信息。

构成每个键以标识分支或条件语句的信息如下(从左到右):

  1. 分支或条件语句类型的标签。

  2. 唯一的标识符。

  3. 它在文件中出现的起始行号。

  4. 它在文件中出现的起始列号。

  5. 它在文件中出现的结束行号。

  6. 它在文件中出现的结束列号。

方法 Coverage

方法覆盖率报告每个方法执行的次数。

[foo_method.rb]
class Greeter
  def greet
    "welcome!"
  end
end

def hello
  "Hi"
end

hello()
Greeter.new.greet()
[EOF]

require "coverage"
Coverage.start(methods: true)
require "foo_method.rb"
p Coverage.result #=> {"foo_method.rb"=>{:methods=>{[Object, :hello, 7, 0, 9, 3]=>1, [Greeter, :greet, 2, 2, 4, 5]=>1}}}

方法哈希中的每个条目表示一个方法。此哈希中的值是该方法执行的次数,键是关于该方法的标识信息。

构成每个键以标识方法的信息如下(从左到右):

  1. 类。

  2. 方法名。

  3. 该方法在文件中出现的起始行号。

  4. 该方法在文件中出现的起始列号。

  5. 该方法在文件中出现的结束行号。

  6. 该方法在文件中出现的结束列号。

所有 Coverage 模式

您也可以使用此快捷方式同时运行所有覆盖率模式。请注意,运行所有覆盖率模式不会同时运行行覆盖率和单次行覆盖率。这些模式不能同时运行。在这种情况下,运行行覆盖率,因为您仍然可以使用它来确定是否执行了某行代码。

require "coverage"
Coverage.start(:all)
require "foo.rb"
p Coverage.result #=> {"foo.rb"=>{:lines=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil], :branches=>{[:if, 0, 6, 0, 10, 3]=>{[:then, 1, 7, 2, 7, 7]=>1, [:else, 2, 9, 2, 9, 7]=>0}}, :methods=>{}}}