mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Measure the test coverage without SimpleCov
Now `make test-all COVERAGE=true` measures the test coverage by using `coverage.so` directly, and visualize the result by simplecov-html. There has been some problems in coverage measurement with SimpleCov. (They are not SimpleCov's fault, though.) (1) It is difficult to extract the measured data as a machine-readable format, such as Marshal. I want to visualize the coverage data with other coverage tools, such as LCOV and Cobertura. (I know we can use SimpleCov's formatter mechanism, but I don't want to depend upon SimpleCov so much.) (2) SimpleCov seems to miss some coverage data. For example, `lib/cgi.rb` and `lib/ostruct.rb` are dropped. I don't know why. (3) I have a plan to enhance `coverage.so` with branch coverage. It would be difficult to continue to only use SimpleCov as is. This is the most important reason. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59770 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
1a643bac88
commit
ccaf52e244
3 changed files with 80 additions and 8 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -116,6 +116,7 @@ lcov*.info
|
|||
/run.gdb
|
||||
/sizes.c
|
||||
/test.rb
|
||||
/test-coverage.dat
|
||||
/tmp
|
||||
/transdb.h
|
||||
/uncommon.mk
|
||||
|
|
|
@ -26,14 +26,7 @@ require_relative 'lib/zombie_hunter'
|
|||
require_relative 'lib/iseq_loader_checker'
|
||||
|
||||
if ENV['COVERAGE']
|
||||
%w[doclie simplecov-html simplecov].each do |f|
|
||||
$LOAD_PATH.unshift "#{src_testdir}/../coverage/#{f}/lib"
|
||||
end
|
||||
|
||||
require 'simplecov'
|
||||
SimpleCov.start do
|
||||
add_filter "/test/"
|
||||
end
|
||||
require "tool/test-coverage.rb"
|
||||
end
|
||||
|
||||
begin
|
||||
|
|
78
tool/test-coverage.rb
Normal file
78
tool/test-coverage.rb
Normal file
|
@ -0,0 +1,78 @@
|
|||
require "coverage"
|
||||
|
||||
Coverage.start
|
||||
|
||||
TEST_COVERAGE_DATA_FILE = "test-coverage.dat"
|
||||
|
||||
def merge_coverage_data(res1, res2)
|
||||
res1.each do |path, cov1|
|
||||
cov2 = res2[path]
|
||||
if cov2
|
||||
cov1.each_with_index do |count1, i|
|
||||
next unless count1
|
||||
if cov2[i]
|
||||
cov2[i] += count1
|
||||
else
|
||||
cov2[i] = count1
|
||||
end
|
||||
end
|
||||
else
|
||||
res2[path] = cov1
|
||||
end
|
||||
end
|
||||
res2
|
||||
end
|
||||
|
||||
def save_coverage_data(res1)
|
||||
File.open(TEST_COVERAGE_DATA_FILE, File::RDWR | File::CREAT | File::BINARY) do |f|
|
||||
f.flock(File::LOCK_EX)
|
||||
s = f.read
|
||||
res2 = s.size > 0 ? Marshal.load(s) : {}
|
||||
res1 = merge_coverage_data(res1, res2)
|
||||
f.rewind
|
||||
f << Marshal.dump(res2)
|
||||
f.flush
|
||||
f.truncate(f.pos)
|
||||
end
|
||||
end
|
||||
|
||||
def invoke_simplecov_formatter
|
||||
%w[doclie simplecov-html simplecov].each do |f|
|
||||
$LOAD_PATH.unshift "#{__dir__}/../coverage/#{f}/lib"
|
||||
end
|
||||
|
||||
require "simplecov"
|
||||
res = Marshal.load(File.binread(TEST_COVERAGE_DATA_FILE))
|
||||
simplecov_result = {}
|
||||
base_dir = File.dirname(__dir__)
|
||||
|
||||
res.each do |path, cov|
|
||||
next unless path.start_with?(base_dir)
|
||||
next if path.start_with?(File.join(base_dir, "test"))
|
||||
simplecov_result[path] = cov
|
||||
end
|
||||
|
||||
res = SimpleCov::Result.new(simplecov_result)
|
||||
res.command_name = "Ruby's `make test-all`"
|
||||
SimpleCov::Formatter::HTMLFormatter.new.format(res)
|
||||
end
|
||||
|
||||
pid = $$
|
||||
pwd = Dir.pwd
|
||||
|
||||
at_exit do
|
||||
exit_exc = $!
|
||||
|
||||
Dir.chdir(pwd) do
|
||||
save_coverage_data(Coverage.result)
|
||||
if pid == $$
|
||||
begin
|
||||
nil while Process.waitpid(-1)
|
||||
rescue Errno::ECHILD
|
||||
invoke_simplecov_formatter
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
raise exit_exc if exit_exc
|
||||
end
|
Loading…
Reference in a new issue