Skip to content

Commit

Permalink
coverageライブラリの説明を追記
Browse files Browse the repository at this point in the history
2.5以降のオプショナルなモードを中心にドキュメントがなかったため、
RDocを参考に意訳しながら、ドキュメントを加筆・整備しました。
  • Loading branch information
universato committed May 19, 2021
1 parent 9c6eb19 commit cb91c19
Showing 1 changed file with 305 additions and 12 deletions.
317 changes: 305 additions & 12 deletions refm/api/src/coverage.rd
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@ category Development

カバレッジを測定するためのライブラリです。

=== 使い方
=== 基本的な使い方

以下のようにして測定を行います。

(1) require "coverage" する
(2) Coverage.start を実行する
(3) require load を実行する
(4) Coverage.result の結果を確認する
(1) require "coverage" で、ライブラリを読み込む。
(2) Coverage.start を実行し、測定を開始する。
(3) require load で測定対象のファイルを実行する。
(4) Coverage.result や Coverage.peek_result で結果を確認する。

=== 例
Coverage.result は、ファイル名をキーとし、カバレッジ測定結果を値とするハッシュを返します。

==== 簡単な例

まず測定対象のソースを用意します。

Expand All @@ -34,10 +36,138 @@ end
require "coverage"
Coverage.start
load "foo.rb"
p Coverage.result # => {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}
p Coverage.result # => {"foo.rb"=>[1, 1, 10, nil, nil, 1, 1, nil, 0, nil]}
#@end

この Coverage.result["foo.rb"] から得られる配列は各行の実行回数になっています。

#@since 2.5.0

=== カバレッジモードの指定

Ruby 2.5 以降では、Coverage.start の引数で、カバレッジで計測種類を変更するモード機能があります。

==== linesカバレッジモード

カバレッジ計測の開始時にカバレッジのモードが明示的に指定されていない場合、Lines カバレッジが実行されます。各行の実行回数を計測します。

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

キーの :lines が指す値は、各行が実行された回数を示す配列です。この配列の順序は重要です。たとえば、この配列の最初の要素は、カバレッジ計測中にファイルの 1 行目が実行された回数を示しています(この例では 1 回)。

なお、空行、コメント、end のような行はカバレッジの計測対象外で、nil となっています。

#@since 2.6.0

==== oneshot_linesカバレッジモード

oneshot_linesカバレッジモードでは、カバレッジの計測中に実行された行を記録します。実行回数は計測せず、実行されたこと行番号を記録します。

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

oneshot_linesキーの指す値は、実行された行番号を列挙した配列です。

#@end

==== branchesカバレッジモード

branchesカバレッジモードでは、各条件分岐のそれぞれの分岐(branch)の実行された回数を計測します。

#@samplecode
require "coverage"
Coverage.start(branches: true)
load "foo.rb"
pp 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}}}}
#@end

キーの :branches が指すハッシュの各キーは条件分岐(の識別情報)であり、
その条件分岐のキーが指すハッシュはその条件分岐の分岐(の識別情報)とその分岐の実行回数です。

分岐の識別情報であるキーを構成する要素は、左から右に向かって以下の通りです。

1. 枝や条件分岐の種類を示すラベル
2. ID(固有の識別子)
3. ファイル内での開始行
4. ファイル内での開始列
5. ファイル内での終了行
6. ファイル内での終了列

==== methodsカバレッジモード

methodsカバレッジモードでは、各メソッドの実行回数を計測します。

#@samplecode foo_method.rb
class Greeter
def greet
"welcome!"
end
end

def hello
"Hi"
end

hello()
Greeter.new.greet()
#@end

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

キーの :methods が指すハッシュの各キーはメソッド(の識別情報)を表し、値はメソッドの実行回数です。

メソッドの識別情報であるキーを構成する要素は、左から右に向かって以下の通りです。

1. クラス名
2. メソッド名
3. ファイル内でのメソッドの開始行
4. ファイル内でのメソッドの開始列
5. ファイル内でのメソッドの終了行
6. ファイル内でのメソッドの終了列

==== 全指定の all

このモードでは、全てのカレッジモードを同時に実行することができます。

#@since 2.6.0
ただし、oneshot_linesカバレッジモードは実行されません。これは、linesカバレッジモードにより各行の実行回数が計測され、行が実行されたかどうかわかるためです。
#@end

#@samplecode
require "coverage"
Coverage.start(:all)
load "foo.rb"
pp 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=>{}}}
#@end

Coverage.result["foo.rb"]から得られる配列は各行の実行回数になっています。
#@end

= class Coverage

Expand All @@ -47,38 +177,169 @@ Coverage.result["foo.rb"]から得られる配列は各行の実行回数にな

== Class Methods

#@until 2.5.0
--- start -> nil

カバレッジの測定を開始します。既に実行されていた場合には何も起こりません。

#@else
--- start(option = {}) -> nil
カバレッジの測定を開始します。既に実行されていた場合には何も起こりません。
ただし、カバレッジ計測中に測定対象を変更しようとした場合は、RuntimeError となります。

@param option カバレッジの計測モードを指定します。
:all か "all" を指定すると、全ての種類を計測します。
個別に指定する場合は、ハッシュを渡します。
詳細は、[[lib:coverage]] を参照してください。

#@samplecode bool.rb
def bool(obj)
if obj
true
else
false
end
end
#@end

#@samplecode
require "coverage"

Coverage.start(:all)
load "bool.rb"
bool(0)
pp Coverage.result
# {"bool.rb"=>
# {:lines=>[1, 1, 1, nil, 0, nil, nil],
# :branches=>
# {[:if, 0, 2, 2, 6, 5]=>
# {[:then, 1, 3, 4, 3, 8]=>1, [:else, 2, 5, 4, 5, 9]=>0}},
# :methods=>{[Object, :bool, 1, 0, 7, 3]=>1}}}

Coverage.start(methods: true)
load "bool.rb"
bool(0)
pp Coverage.result #=> {"bool.rb"=>{:methods=>{[Object, :bool, 1, 0, 7, 3]=>1}}}
#@end

#@end

#@since 2.6.0
--- result(stop: true, clear: true) -> Hash
#@else
--- result -> Hash
#@end

#@since 2.5.0
対象ファイル名をキー、測定結果を値したハッシュを返します。
測定結果の詳細は、[[lib:coverage]] を参照してください。
#@else
測定結果をファイル名をキー、各行の実行回数を配列にした値のハッシュを返
します。空行やコメントのみの行などの測定結果は nil になります。result
メソッドが実行された後はカバレッジの測定を行いません。
します。空行やコメントのみの行などの測定結果は nil になります。
#@end

#@since 2.6.0
@param stop true であれば、カバレッジの測定を終了します。
@param clear true であれば、測定記録をクリアにします。
#@else
resultメソッドが実行された後はカバレッジの測定を行いません。
#@end

@return 測定結果を表すハッシュ

@raise RuntimeError [[m:Coverage.start]] を実行する前に実行された場合に
発生します。

#@samplecode bool.rb
def bool(obj)
if obj
true
else
false
end
end
#@end

#@samplecode
require "coverage"
Coverage.start
load "bool.rb"
p Coverage.result #=> {"bool.rb"=>[1, 0, 0, nil, 0, nil, nil]}
bool(0)
p Coverage.result # coverage measurement is not enabled (RuntimeError)
#@end

#@since 2.6.0
Ruby 2.6 以降では、オプションを指定できます。
Coverage.result(clear: true, stop: false) と指定することで、続けて新しく実行された行だけを記録することができます。

#@samplecode
require "coverage"
Coverage.start(oneshot_lines: true)
load "bool.rb"
p Coverage.result(clear: true, stop: false) #=> {"bool.rb"=>{:oneshot_lines=>[1]}}
bool(0)
p Coverage.result(clear: true, stop: false) #=> {"bool.rb"=>{:oneshot_lines=>[2, 3]}}
bool(nil)
p Coverage.result(clear: true, stop: false) #=> {"bool.rb"=>{:oneshot_lines=>[5]}}
#@end

上記のコード例で、bool(0) で実行された2行目の条件式は、測定記録がクリアされたあと bool(nil) で実行されても新しく記録されません。
測定記録をクリアしても、記録を開始してから実行されたことまでリセットされているわけではないことに注意して下さい。
#@end

@see [[m:Coverage.peek_result]]
--- peek_result -> Hash

測定途中結果をファイル名をキー、各行の実行回数を配列にした値のハッシュを返
#@since 2.5.0
測定を止めることなく、測定中のその時の結果をハッシュで返します。
測定結果の詳細は、[[lib:coverage]] を参照してください。
#@else
測定途中の結果をファイル名をキー、各行の実行回数を配列にした値のハッシュで返
します。空行やコメントのみの行などの測定結果は nil になります。
#@end

#@since 2.6.0
これは、Coverage.result(stop: false, clear: false) と同じです。
#@end

@return 測定途中結果を表すハッシュ

@raise RuntimeError [[m:Coverage.start]] を実行する前に実行された場合に
発生します。

#@samplecode bool.rb
def bool(obj)
if obj
true
else
false
end
end
#@end

#@samplecode
require "coverage"

Coverage.start

load "bool.rb"
p Coverage.peek_result #=> {"bool.rb"=>[1, 0, 0, nil, 0, nil, nil]}

bool(true)
p Coverage.peek_result #=> {"bool.rb"=>[1, 1, 1, nil, 0, nil, nil]}

bool(false)
p Coverage.peek_result #=> {"bool.rb"=>[1, 2, 1, nil, 1, nil, nil]}
#@end

@see [[m:Coverage.result]]

#@since 2.5.0
--- running? -> bool

カバレッジ測定中かどうかを返します。
カバレッジ測定中かどうかを返します。カバレッジの測定中とは、Coverage.start の
呼び出し後から Coverage.result の呼び出し前です。

#@samplecode
require 'coverage'
Expand All @@ -91,3 +352,35 @@ p Coverage.result #=> {}
p Coverage.running? #=> false
#@end
#@end

#@since 2.6.0
--- line_stub(file) -> Array

行カバレッジの配列のスタブを返します。

測定対象となる行の要素は 0, 空行やコメントなどにより測定対象外となる行の要素は nil となります。

#@samplecode foo.rb
s = 0
10.times do |x|
s += x
end

if s == 45
p :ok
else
p :ng
end
#@end

このファイルに対して line_stub を実行すると、次のようになります。

#@samplecode
require "coverage"
p Coverage.line_stub("foo.rb") #=> [0, 0, 0, nil, nil, 0, 0, nil, 0, nil]
#@end

この例において、空行, else, end の行は測定対象外であるため、nil となっています。

@param file ファイル名を表す文字列
#@end

0 comments on commit cb91c19

Please sign in to comment.