💯
ruby のカバレッジを vscode で可視化する
ruby には Coverage
という組み込み class があり、簡単にカバレッジを計測できます。
以下のようにするだけで rspec を実行しつつカバレッジを取得できます。
RSpec.configure do |config|
config.before :suite do
Coverage.start
end
config.after :suite do
# Coverage.result を出力
end
end
vscode でカバレッジを表示するツールを検索し、以下の2つを発見しました。
まず1つ目は、ファイル内の行ごとにインジケータを表示してくれる Coverage Gutters
2つ目は、ファイルツリーでカバレッジをパーセンテージ表示してくれる Koverage
どちらも lcov というフォーマットに対応しているので、 Coverage
の結果を lcov に変換すればこれらのツールを使って可視化ができます。
lcov はシンプルなテキストファイルで、以下の comment に仕様がまとまっていました。
TN: test name
SF: source file path
FN: line number,function name
FNF: number functions found
FNH: number hit
BRDA: branch data: line, block, (expressions,count)+
BRF: branches found
DA: line number, hit count
LF: lines found
LH: lines hit.
この中から、 Coverage Gutters と Koverage が対応している SF
と DA
をとりあえず出力することにします。
def write_lcov(result)
# result には gem の中のファイルも全て含んでいるので、カレントディレクトリ以下のみを抽出
ret = result.filter{|k,v| k.starts_with? Dir.pwd }
open('lcov.info', 'w') do |f|
ret.each do |k,v|
f.puts "SF:#{k}" # source file path
# line_stub は ruby ファイル内の実行可能行のリストを返す
line_stub = Coverage.line_stub(k)
line_stub.each.with_index(1) do |l,i|
next if l.nil?
hit = v[:oneshot_lines].include?(i)
f.puts "DA:#{i},#{hit ? 1 : 0}" # line number, hit count
end
f.puts "end_of_record"
end
end
end
後は、 Coverage の result を渡すように先ほどの RSpec.configure
を少し書き換えます。
RSpec.configure do |config|
if ENV['COV']
config.before(:suite) { Coverage.start(oneshot_lines: true) }
config.after :suite do
write_lcov(Coverage.result)
end
end
end
これで、 COV=1 bin/rspec
などと実行すれば lcov.info
が出力され、 Coverage gutters と koverage が結果を可視化してくれます。
Discussion