aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-07 15:40:29 +0000
committermame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-09-07 15:40:29 +0000
commitbb03c9b515e4823bef3ad781c79de06d456c39f2 (patch)
treef8d575910c93a43ed7bb8d2081a595064e080b55
parent371f6a19a2fbe8d5f325bd66b58b90d5f7cefe5f (diff)
downloadruby-bb03c9b515e4823bef3ad781c79de06d456c39f2.tar.gz
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
-rw-r--r--.gitignore1
-rw-r--r--test/runner.rb9
-rw-r--r--tool/test-coverage.rb78
3 files changed, 80 insertions, 8 deletions
diff --git a/.gitignore b/.gitignore
index a5567a0271..5517f80fad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -116,6 +116,7 @@ lcov*.info
/run.gdb
/sizes.c
/test.rb
+/test-coverage.dat
/tmp
/transdb.h
/uncommon.mk
diff --git a/test/runner.rb b/test/runner.rb
index 1fe32fcfc8..02cc4610df 100644
--- a/test/runner.rb
+++ b/test/runner.rb
@@ -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
diff --git a/tool/test-coverage.rb b/tool/test-coverage.rb
new file mode 100644
index 0000000000..0c002f4d1a
--- /dev/null
+++ b/tool/test-coverage.rb
@@ -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