minitest-coverage 1.0.0.b1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 86bcc7a21e9f3139f23a5b705948c08a6556a096
4
+ data.tar.gz: 86387a496d64055c920b5f7fb37a793c6c747521
5
+ SHA512:
6
+ metadata.gz: ee5f01db049c2c840c96dbde539fa237815a066b77fb4b5304ebcd9150c4983735922e60354b72adcdc5b23d63670ae0821a17e347365a49bcba44e7e2ca757c
7
+ data.tar.gz: b839b72737afdbea82c9f3891b940728c93d563af43e13c56557ecc28f95a57c02bf1b9e877889124ddc8443cf3b629547e9e4437ef3a97d2deee86ca1f041d7
checksums.yaml.gz.sig ADDED
Binary file
data.tar.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+ �2��������TY�z6�ʸ��v4��{�AdY��Ԗr��s
2
+ �o�<
3
+ ���%�����[T�����9rl���;n�<þ^�����nc
data/.autotest ADDED
@@ -0,0 +1,26 @@
1
+ # -*- ruby -*-
2
+
3
+ require "autotest/restart"
4
+
5
+ Autotest.add_hook :initialize do |at|
6
+ at.testlib = "minitest/autorun"
7
+ at.add_exception "tmp"
8
+
9
+ # at.extra_files << "../some/external/dependency.rb"
10
+ #
11
+ # at.libs << ":../some/external"
12
+ #
13
+ # at.add_exception "vendor"
14
+ #
15
+ # at.add_mapping(/dependency.rb/) do |f, _|
16
+ # at.files_matching(/test_.*rb$/)
17
+ # end
18
+ #
19
+ # %w(TestA TestB).each do |klass|
20
+ # at.extra_class_map[klass] = "test/test_misc.rb"
21
+ # end
22
+ end
23
+
24
+ # Autotest.add_hook :run_command do |at|
25
+ # system "rake build"
26
+ # end
data/History.rdoc ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0.b1 / 2016-09-12
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,21 @@
1
+ .autotest
2
+ History.rdoc
3
+ Manifest.txt
4
+ README.rdoc
5
+ Rakefile
6
+ add_coverage_result_set.patch
7
+ bin/minitest_coverage
8
+ bin/minitest_coverage_baseline
9
+ bin/minitest_coverage_issues
10
+ bin/minitest_coverage_report
11
+ example/lib/example.rb
12
+ example/lib/indirect.rb
13
+ example/test/test_example.rb
14
+ example/test/test_indirect.rb
15
+ lib/coverage/dumper.rb
16
+ lib/coverage/pruner.rb
17
+ lib/coverage/start.rb
18
+ lib/minitest/coverage.rb
19
+ lib/minitest/coverage_plugin.rb
20
+ minitest-coverage.el
21
+ test/minitest/test_coverage.rb
data/README.rdoc ADDED
@@ -0,0 +1,118 @@
1
+ = minitest-coverage
2
+
3
+ home :: https://github.com/seattlerb/minitest-coverage
4
+ rdoc :: http://docs.seattlerb.org/minitest-coverage
5
+
6
+ == DESCRIPTION:
7
+
8
+ Ruby's contemporary test coverage tools all lie, exaggerating coverage
9
+ through false-positives and creating a false sense of security;
10
+ minitest-coverage tries to address this.
11
+
12
+ Coverage Analysis Tools rely on tracing facilities built into ruby’s
13
+ VM. You run your tests, and collect data. Seems simple, but that’s a
14
+ very flawed approach that buffers your coverage numbers up falsely.
15
+ I’ve witnessed false coverage by as much as 60%, but it could be even
16
+ worse. Worse, the tracing facilities currently make it impossible to
17
+ get truly accurate numbers. Even so, they can be improved to be much
18
+ more accurate.
19
+
20
+ == FEATURES/PROBLEMS:
21
+
22
+ * Honest test coverage analysis, prone to false negative, not false positive.
23
+ * Allows you to record a baseline of your implementation and cache it.
24
+ * Allows you to run a subset of your tests with the baseline.
25
+ * Allows you to run subsets of your tests and merge them on report.
26
+ * Doesn't require fully mocked tests for accurate coverage analysis.
27
+ * Filters results down to the class-under-test to remove false positives.
28
+ * FIX: Fails to map some tests back to implementation because of naming mismatches.
29
+ * TODO: doesn't yet integrate with simplecov's html report system.
30
+ * TODO: beta beta beta
31
+ * TODO: make fallback code more accurate with manual baseline accounting?
32
+
33
+ == SYNOPSIS:
34
+
35
+ # create baseline in production mode to force load all models & controllers
36
+ % minitest_coverage_baseline
37
+ % mv coverage.json baseline.json
38
+
39
+ # run tests in full or in part:
40
+ % minitest_coverage --coverage=baseline.json 'test/unit/**/*_test.rb'
41
+ % mv coverage.json coverage.unit.json
42
+
43
+ % minitest_coverage --coverage=baseline.json 'test/{functional,controllers}/**/*_test.rb'
44
+ % mv coverage.json coverage.fun.json
45
+
46
+ # generate a report
47
+ % minitest_coverage_report baseline.json coverage.unit.json coverage.fun.json
48
+
49
+ uncv covr% totl : path
50
+
51
+ 403 4.5% 422 : app/models/option_expense_report/oer_export.rb
52
+ 322 11.0% 362 : app/models/certificate_expense.rb
53
+ 262 7.4% 283 : app/models/option_expense_report_processor.rb
54
+ 237 25.2% 317 : app/controllers/transactions_controller.rb
55
+ 209 19.9% 261 : app/models/concerns/excel_sheet.rb
56
+ 166 13.1% 191 : app/models/summary_captable.rb
57
+ 148 25.3% 198 : app/concerns/formula.rb
58
+ 142 10.7% 159 : app/helpers/valuation_reports_helper.rb
59
+ 132 33.0% 197 : app/models/public_comp_list.rb
60
+ 122 28.7% 171 : app/controllers/permissions_controller.rb
61
+ 120 28.1% 167 : lib/importer.rb
62
+ 115 36.1% 180 : app/controllers/workflows_controller.rb
63
+ 110 46.9% 207 : app/helpers/transactions_helper.rb
64
+ 101 35.3% 156 : app/models/ma_comp_list.rb
65
+ 97 36.2% 152 : app/models/option_expense_report.rb
66
+
67
+ [869 lines skipped]
68
+
69
+ Actual Coverage = 12912 / 24621 = 52.44%
70
+
71
+ == REQUIREMENTS:
72
+
73
+ * Ruby, patched currently. :(
74
+ * minitest + tests in minitest
75
+
76
+ == INSTALL:
77
+
78
+ * gem install minitest-coverage
79
+
80
+ === Custom Ruby
81
+
82
+ This currently requires a patch against ruby to work well. The easiest
83
+ way to handle this is probably with rbenv+ruby-build or rvm.
84
+
85
+ The patch SHOULD apply cleanly against 2.3.x, 2.4, and trunk/master.
86
+
87
+ === For rbenv+ruby-build:
88
+
89
+ curl -L http://github.com/ruby/ruby/pull/1456.patch | rbenv install -p 2.4.0-preview1
90
+
91
+ === For rvm:
92
+
93
+ rvm install 2.4.0-preview1 --patch http://github.com/ruby/ruby/pull/1456.patch
94
+
95
+ == LICENSE:
96
+
97
+ (The MIT License)
98
+
99
+ Copyright (c) Ryan Davis, seattle.rb
100
+
101
+ Permission is hereby granted, free of charge, to any person obtaining
102
+ a copy of this software and associated documentation files (the
103
+ 'Software'), to deal in the Software without restriction, including
104
+ without limitation the rights to use, copy, modify, merge, publish,
105
+ distribute, sublicense, and/or sell copies of the Software, and to
106
+ permit persons to whom the Software is furnished to do so, subject to
107
+ the following conditions:
108
+
109
+ The above copyright notice and this permission notice shall be
110
+ included in all copies or substantial portions of the Software.
111
+
112
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
113
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
114
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
115
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
116
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
117
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
118
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # -*- ruby -*-
2
+
3
+ require "rubygems"
4
+ require "hoe"
5
+
6
+ Hoe.plugin :isolate
7
+ Hoe.plugin :seattlerb
8
+ Hoe.plugin :rdoc
9
+
10
+ Hoe.spec "minitest-coverage" do
11
+ developer "Ryan Davis", "ryand-ruby@zenspider.com"
12
+
13
+ self.need_rdoc = false
14
+
15
+ license "MIT"
16
+ end
17
+
18
+ # vim: syntax=ruby
@@ -0,0 +1,52 @@
1
+ commit c6e1784e9ec10f34e07c20c687004df9d3a84732
2
+ Author: Ryan Davis <ryand-ruby@zenspider.com>
3
+ Date: Wed Oct 5 17:09:27 2016 -0700
4
+
5
+ Added Coverage.result=.
6
+
7
+ diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c
8
+ index 9a9011a..6b7457c 100644
9
+ --- a/ext/coverage/coverage.c
10
+ +++ b/ext/coverage/coverage.c
11
+ @@ -75,6 +75,34 @@ rb_coverage_result(VALUE klass)
12
+ return ncoverages;
13
+ }
14
+
15
+ +static int
16
+ +coverage_merge_result_i(VALUE path, VALUE coverage, VALUE coverages)
17
+ +{
18
+ + VALUE ary = rb_hash_lookup2(coverages, path, Qnil);
19
+ +
20
+ + if (RTEST(ary)) {
21
+ + rb_ary_replace(ary, coverage);
22
+ + }
23
+ +
24
+ + return ST_CONTINUE;
25
+ +}
26
+ +
27
+ +static VALUE
28
+ +rb_coverage_set_result(VALUE klass, VALUE ncoverages)
29
+ +{
30
+ + VALUE coverages = rb_get_coverages();
31
+ +
32
+ + Check_Type(ncoverages, T_HASH);
33
+ +
34
+ + if (!RTEST(coverages)) {
35
+ + rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
36
+ + }
37
+ +
38
+ + rb_hash_foreach(ncoverages, coverage_merge_result_i, coverages);
39
+ +
40
+ + return ncoverages;
41
+ +}
42
+ +
43
+ /* Coverage provides coverage measurement feature for Ruby.
44
+ * This feature is experimental, so these APIs may be changed in future.
45
+ *
46
+ @@ -114,5 +142,6 @@ Init_coverage(void)
47
+ VALUE rb_mCoverage = rb_define_module("Coverage");
48
+ rb_define_module_function(rb_mCoverage, "start", rb_coverage_start, 0);
49
+ rb_define_module_function(rb_mCoverage, "result", rb_coverage_result, 0);
50
+ + rb_define_module_function(rb_mCoverage, "result=", rb_coverage_set_result, 1);
51
+ rb_define_module_function(rb_mCoverage, "peek_result", rb_coverage_peek_result, 0);
52
+ }
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << "lib"
4
+ $: << "test"
5
+ $: << "."
6
+
7
+ require "coverage/start"
8
+ require "minitest/autorun"
9
+
10
+ new_argv = []
11
+
12
+ ARGV.each do |path_or_glob|
13
+ if path_or_glob =~ /^[\d-]/ then
14
+ new_argv << path_or_glob
15
+ else
16
+ Dir[path_or_glob].each do |path|
17
+ next unless File.file? path
18
+ load path
19
+ end
20
+ end
21
+ end
22
+
23
+ ARGV.replace new_argv
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $: << "lib"
4
+ $: << "."
5
+
6
+ require "coverage/start"
7
+
8
+ path = "./config/environment.rb"
9
+
10
+ if File.file? path then
11
+ ENV["RAILS_ENV"] = "production"
12
+ require path
13
+ end
14
+
15
+ # TODO: app/** shouldn't be necessary given RAILS_ENV + environment.rb above.
16
+ Dir["app/**/*.rb", "lib/**/*.rb"].each do |path|
17
+ begin
18
+ warn path
19
+ require path
20
+ rescue StandardError, SyntaxError => e # for badly named ERB files
21
+ warn "Skipping #{e.inspect}"
22
+ end
23
+ end
24
+
25
+ require "coverage/pruner"
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/ruby -ws
2
+
3
+ $n ||= false
4
+
5
+ require "json"
6
+
7
+ class Float
8
+ def floor_ n=0
9
+ m = 10**n
10
+ (self*m).floor.to_f / m
11
+ end
12
+ end
13
+
14
+ def issues name, pct
15
+ pcts = [pct] + pct.floor_(1).step(1.0, 0.1).drop(1).to_a
16
+ prev = nil
17
+
18
+ pcts.each_cons 2 do |from, to|
19
+ msg = "Increase coverage of %s from %6.2f%% to %6.2f%%" %
20
+ [name, from*100.0, to*100.0]
21
+
22
+ if prev then
23
+ msg << "\n\nSee #{prev}"
24
+ end
25
+
26
+ cmd = "hub issue create -m \"#{msg}\""
27
+
28
+ if $n then
29
+ puts cmd
30
+ else
31
+ prev = `#{cmd}`
32
+ end
33
+ end
34
+ end
35
+
36
+ file_re = ARGV.empty? ? /./ : Regexp.union(*ARGV)
37
+
38
+ Dir["coverage.json"].each do |path| # cheat
39
+ data = JSON.load File.read path
40
+ re = /#{File.basename(File.dirname(path), "_test.rb").tr "_", "."}/
41
+
42
+ cov_data = data["Unit Tests"]["coverage"]
43
+ keys = cov_data.keys.grep re
44
+
45
+ unless keys.empty? then
46
+ keys.each do |key| # TODO: this is confusing. Just grab first
47
+ file = cov_data[key]
48
+ name = key[/(app|lib)\/.*/] || key
49
+ max = file.compact.size
50
+ n = max - file.count(0)
51
+
52
+ next unless name =~ file_re
53
+
54
+ issues name, n.to_f/max
55
+ end
56
+ else
57
+ next unless path =~ file_re
58
+ name = File.basename(File.dirname(path))
59
+ issues name, 0.0
60
+ end
61
+ end
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/ruby -w
2
+
3
+ require "json"
4
+
5
+ cover_lines = 0
6
+ total_lines = 0
7
+
8
+ data = {}
9
+
10
+ ARGV.each do |input_path|
11
+ warn input_path
12
+ File.open input_path do |file|
13
+ data.merge! JSON.load file
14
+ end
15
+ end
16
+
17
+ puts "uncv covr% totl : path"
18
+ puts
19
+ puts data.map { |path, lines|
20
+ name = path[/(app|lib|config)\/.*/]
21
+ next unless name
22
+ abort "Bad path: #{path.inspect}" unless name
23
+ next if path =~ /^config/
24
+
25
+ max = lines.compact.size
26
+ n = max - lines.count(0)
27
+
28
+ cover_lines += n
29
+ total_lines += max
30
+
31
+ if max > 0 then
32
+ pct = n.to_f/max
33
+ uncovered = max-max*pct
34
+ "%4d %5.1f%% %4d : %s" % [uncovered, 100.0*pct, max, name]
35
+ else
36
+ "%4d %5.1f%% %4d : %s" % [0, 100, max, name]
37
+ end
38
+ }.compact.sort.reverse
39
+
40
+ puts "Actual Coverage = %d / %d = %.2f%%" % [cover_lines, total_lines, 100.0*cover_lines/total_lines]
@@ -0,0 +1,9 @@
1
+ class Example
2
+ def x
3
+ y
4
+ end
5
+
6
+ def y
7
+ 42
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ require "example"
2
+
3
+ class Indirect
4
+ def x
5
+ Example.new.x
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ require "minitest/autorun"
2
+ require "example"
3
+
4
+ class TestExample < Minitest::Test
5
+ def test_y
6
+ assert_equal 42, Example.new.y
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require "minitest/autorun"
2
+ require "indirect"
3
+
4
+ class TestIndirect < Minitest::Test
5
+ def test_y
6
+ assert_equal 42, Indirect.new.x
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ require "json"
2
+ require "coverage/start"
3
+
4
+ at_exit { # get behind minitest if we're running alongside
5
+ at_exit {
6
+ coverage = Coverage.result
7
+
8
+ File.open "coverage.json", "w" do |f|
9
+ f.puts JSON.pretty_generate coverage
10
+ end
11
+ }
12
+ }
@@ -0,0 +1,15 @@
1
+ require "json"
2
+ require "coverage/start"
3
+
4
+ pwd_re = Regexp.union Dir.pwd
5
+ pruner = lambda { |k,_| k !~ pwd_re }
6
+
7
+ at_exit { # get behind minitest if we're running alongside
8
+ at_exit {
9
+ coverage = Coverage.result.reject(&pruner)
10
+
11
+ File.open "coverage.json", "w" do |f|
12
+ f.puts JSON.pretty_generate coverage
13
+ end
14
+ }
15
+ }
@@ -0,0 +1,3 @@
1
+ require "coverage"
2
+ puts "Starting coverage"
3
+ Coverage.start
@@ -0,0 +1,156 @@
1
+ module Minitest; end
2
+
3
+ module Minitest
4
+ module CoverageRunner
5
+ VERSION = "1.0.0.b1"
6
+
7
+ def self.coverage_baseline
8
+ @@coverage_baseline
9
+ end
10
+
11
+ def self.coverage_baseline= o
12
+ @@coverage_baseline = o
13
+ end
14
+
15
+ def coverage_baseline
16
+ @@coverage_baseline
17
+ end
18
+
19
+ def self.coverage_data
20
+ @@coverage_data
21
+ end
22
+
23
+ def self.coverage_data= o
24
+ @@coverage_data = o
25
+ end
26
+
27
+ def coverage_data
28
+ @@coverage_data
29
+ end
30
+
31
+ # Marshal to unfreeze (frozen state depends on ruby version?)
32
+ self.coverage_baseline = Marshal.load Marshal.dump Coverage.peek_result
33
+
34
+ # full dupe of baseline
35
+ self.coverage_data = Marshal.load Marshal.dump coverage_baseline
36
+
37
+ def clean_path path
38
+ path[Dir.pwd.length+1..-1]
39
+ end
40
+
41
+ def coverage_diff test_name, new, old
42
+ puts
43
+
44
+ path, lines = find_path_and_lines(new, test_name)
45
+
46
+ return unless path && lines
47
+
48
+ old_lines = old[path] || lines.map { |x| x ? 0 : nil }
49
+
50
+ print " #{clean_path path}"
51
+ a, b, max = pct(old_lines), pct(lines), max(lines)
52
+
53
+ if (a - b).abs < 0.01 then
54
+ puts ": no change at %.1f%% of %d lines" % [a, max]
55
+ else
56
+ puts ": from %.1f%% to %.1f%% of %d lines" % [a, b, max]
57
+ end
58
+ end
59
+
60
+ PWD = Dir.pwd
61
+
62
+ def find_path_and_lines coverage, test_name
63
+ impl_re = /\/#{impl_name test_name}$/
64
+
65
+ coverage.sort.find { |path, lines| # sorting biases towards app and lib
66
+ next unless path.start_with? PWD
67
+ path =~ impl_re
68
+ }
69
+ end
70
+
71
+ def impl_name test_name
72
+ unless test_name then
73
+ p :nil => [test_name, self.name]
74
+ p caller
75
+ abort
76
+ end
77
+ (test_name[/^([\w:]+?)Test/, 1] || # rails style
78
+ test_name[/^Test([\w:]+)$/, 1] || # ruby style
79
+ test_name). # give up
80
+ gsub(/([a-z])([A-Z])/, '\1_\2').
81
+ gsub(/::/, "/").
82
+ downcase + "\\.rb"
83
+ rescue => e
84
+ p e
85
+ p test_name
86
+ p test_name[/^([\w:]+?)Test(?:::)?/, 1]
87
+ raise e
88
+ end
89
+
90
+ def max lines
91
+ lines.compact.size
92
+ end
93
+
94
+ def merge_coverage new_coverage
95
+ path, lines = find_path_and_lines new_coverage, self.name
96
+
97
+ if path and lines then
98
+ coverage_data[path] = lines
99
+ else
100
+ # warn "Bad mapping for #{self.name}. Skipping coverage." # TODO
101
+ end
102
+ end
103
+
104
+ def output_coverage
105
+ require "json"
106
+
107
+ cleaned = coverage_data.reject { |path, lines|
108
+ path.nil? or
109
+ path.include? RbConfig::CONFIG["libdir"] or
110
+ not path.start_with? PWD
111
+ }
112
+
113
+ File.open "coverage.json", "w" do |f|
114
+ f.puts JSON.pretty_generate cleaned
115
+ end
116
+
117
+ warn "created coverage.json"
118
+ end
119
+
120
+ module_function :output_coverage
121
+
122
+ def pct lines
123
+ max = max lines
124
+ n = max - lines.count(0)
125
+ 100.0*n/max
126
+ end
127
+
128
+ def run *args
129
+ return if self.runnable_methods.empty?
130
+
131
+ unless impl_name self.name then
132
+ warn "BAD NAME: #{self.name} -- can't map to implementation. Skipping"
133
+ end
134
+
135
+ puts
136
+ puts "#{self.name}:"
137
+
138
+ super
139
+
140
+ new_coverage = Coverage.peek_result
141
+
142
+ coverage_diff(self.name, new_coverage, coverage_data)
143
+ merge_coverage new_coverage
144
+
145
+ if Coverage.respond_to? :result= then
146
+ Coverage.result = coverage_baseline
147
+ else
148
+ @@coverage_warning ||= false
149
+ unless @@coverage_warning then
150
+ warn "Unable to reset coverage baseline. Numbers will be artificially high."
151
+ @@coverage_warning = true
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,39 @@
1
+ require "coverage"
2
+ Coverage.start
3
+
4
+ require "minitest"
5
+ require "pp"
6
+
7
+ module Minitest
8
+ @coverage = false
9
+
10
+ def self.plugin_coverage_options opts, options # :nodoc:
11
+ opts.on "-c", "--coverage [BASELINE]", String, "Generate coverage reports." do |s|
12
+ require "coverage/start"
13
+ # TODO: maybe warn about this being too late in the process?
14
+
15
+ unless Coverage.respond_to? :peek_result then
16
+ abort "ABORTING: minitest-coverage only works on ruby 2.3+"
17
+ end
18
+
19
+ @coverage = s || true
20
+ end
21
+ end
22
+
23
+ def self.plugin_coverage_init options # :nodoc:
24
+ if @coverage then
25
+ require "coverage"
26
+ require "minitest/coverage"
27
+ Minitest::Test.singleton_class.prepend Minitest::CoverageRunner
28
+
29
+ if String === @coverage then
30
+ require "json"
31
+ Minitest::CoverageRunner.coverage_baseline = JSON.load File.read @coverage
32
+ end
33
+
34
+ Minitest.after_run do
35
+ Minitest::CoverageRunner.output_coverage
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,63 @@
1
+ (defface mtc-uncovered
2
+ '((t :background "#ffdddd"))
3
+ "Face for uncovered lines of code"
4
+ :group 'mtc)
5
+
6
+ (defface mtc-covered
7
+ '((t :background "#ddffdd" :inherit region))
8
+ "Face for covered lines of code"
9
+ :group 'mtc)
10
+
11
+ (defun mtc-overlay (coverage-path)
12
+ (let ((coverage (assoc (intern (buffer-file-name))
13
+ (json-read-file coverage-path))))
14
+ (when coverage
15
+ (let ((coverage (cdr coverage))
16
+ (line-pos
17
+ (save-excursion
18
+ (goto-char (point-min))
19
+ (mapcar (lambda (n) (cons (line-beginning-position n)
20
+ (line-end-position n)))
21
+ (number-sequence 1 (line-number-at-pos (point-max)))))))
22
+ (remove-overlays)
23
+ (mapcar* (lambda (cov range)
24
+ (when cov
25
+ (let ((start (car range))
26
+ (stop (cdr range))
27
+ (color (if (zerop cov) 'mtc-uncovered 'mtc-covered)))
28
+ (if nil
29
+ ;; bad w/ font-lock
30
+ (with-silent-modifications
31
+ (put-text-property start stop 'font-lock-face color))
32
+ ;; bad with highlighted region
33
+ (overlay-put (make-overlay start stop)
34
+ 'face
35
+ ;; (cons 'background-color color)
36
+ (list color)))
37
+ )))
38
+ coverage line-pos)))))
39
+
40
+ (defun mtc-find-project-file (file &optional dir)
41
+ (or dir (setq dir default-directory))
42
+ (let ((file-path (concat (file-name-as-directory dir) file)))
43
+ (if (file-exists-p file-path)
44
+ file-path
45
+ (if (equal dir "/")
46
+ nil
47
+ (mtc-find-project-file file
48
+ (directory-file-name (file-name-directory dir)))))))
49
+
50
+ (defun mtc-update ()
51
+ (interactive)
52
+ (let ((coverage-path (mtc-find-project-file "coverage.json")))
53
+ (when coverage-path
54
+ (mtc-clear)
55
+ (mtc-overlay coverage-path)
56
+ nil)))
57
+
58
+ (defun mtc-clear ()
59
+ (interactive)
60
+ (remove-overlays))
61
+
62
+ ;; (with-current-buffer (window-buffer (next-window)) (mtc-update))
63
+ ;; (with-current-buffer (window-buffer (next-window)) (mtc-clear))
@@ -0,0 +1,69 @@
1
+ require "json"
2
+ require "coverage/start"
3
+ require "minitest/autorun"
4
+ require "minitest/coverage"
5
+
6
+ module TestMinitest; end
7
+
8
+ class TestMinitest::TestCoverage < Minitest::Test
9
+ attr_accessor :data
10
+
11
+ CPATH = "coverage.json"
12
+ N = nil
13
+
14
+ def teardown
15
+ File.unlink CPATH
16
+ end
17
+
18
+ def cover *paths
19
+ cmd = [
20
+ RbConfig.ruby,
21
+ "-Ilib",
22
+ "-I../../minitest/dev/lib",
23
+ "-Iexample/lib",
24
+ "bin/minitest_coverage",
25
+ *paths,
26
+ "-v",
27
+ "--seed", "41015",
28
+ "--coverage",
29
+ ]
30
+
31
+ Process.wait spawn(*cmd, :out => "/dev/null", :err => "/dev/null")
32
+
33
+ assert_operator File, :file?, CPATH
34
+ self.data = JSON.load File.read CPATH
35
+ end
36
+
37
+ def path path
38
+ File.join Dir.pwd, path
39
+ end
40
+
41
+ def assert_coverage path, exp
42
+ if exp then
43
+ assert_equal exp, data[path(path)]
44
+ else
45
+ assert_nil data[path(path)]
46
+ end
47
+ end
48
+
49
+ def test_indirect
50
+ cover "example/test/test_indirect.rb"
51
+
52
+ assert_coverage "example/lib/indirect.rb", [1, N, 1, 1, 1, N, N]
53
+ assert_coverage "example/lib/example.rb", [1, 1, 0, N, N, 1, 0, N, N]
54
+ end
55
+
56
+ def test_example
57
+ cover "example/test/test_example.rb"
58
+
59
+ assert_coverage "example/lib/indirect.rb", N
60
+ assert_coverage "example/lib/example.rb", [1, 1, 0, N, N, 1, 1, N, N] # x intentionally not covered
61
+ end
62
+
63
+ def test_combined
64
+ cover "example/test/test_example.rb", "example/test/test_indirect.rb"
65
+
66
+ assert_coverage "example/lib/indirect.rb", [1, N, 1, 1, 1, N, N]
67
+ assert_coverage "example/lib/example.rb", [1, 1, 0, N, N, 1, 1, N, N]
68
+ end
69
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minitest-coverage
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.b1
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Davis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDijCCAnKgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMRMwEQYDVQQDDApyeWFu
14
+ ZC1ydWJ5MRkwFwYKCZImiZPyLGQBGRYJemVuc3BpZGVyMRMwEQYKCZImiZPyLGQB
15
+ GRYDY29tMB4XDTE2MDkyNjAxNTczNVoXDTE3MDkyNjAxNTczNVowRTETMBEGA1UE
16
+ AwwKcnlhbmQtcnVieTEZMBcGCgmSJomT8ixkARkWCXplbnNwaWRlcjETMBEGCgmS
17
+ JomT8ixkARkWA2NvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALda
18
+ b9DCgK+627gPJkB6XfjZ1itoOQvpqH1EXScSaba9/S2VF22VYQbXU1xQXL/WzCkx
19
+ taCPaLmfYIaFcHHCSY4hYDJijRQkLxPeB3xbOfzfLoBDbjvx5JxgJxUjmGa7xhcT
20
+ oOvjtt5P8+GSK9zLzxQP0gVLS/D0FmoE44XuDr3iQkVS2ujU5zZL84mMNqNB1znh
21
+ GiadM9GHRaDiaxuX0cIUBj19T01mVE2iymf9I6bEsiayK/n6QujtyCbTWsAS9Rqt
22
+ qhtV7HJxNKuPj/JFH0D2cswvzznE/a5FOYO68g+YCuFi5L8wZuuM8zzdwjrWHqSV
23
+ gBEfoTEGr7Zii72cx+sCAwEAAaOBhDCBgTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE
24
+ sDAdBgNVHQ4EFgQUR8V72Z3+v+2P9abCnL4wjx32T+EwIwYDVR0RBBwwGoEYcnlh
25
+ bmQtcnVieUB6ZW5zcGlkZXIuY29tMCMGA1UdEgQcMBqBGHJ5YW5kLXJ1YnlAemVu
26
+ c3BpZGVyLmNvbTANBgkqhkiG9w0BAQUFAAOCAQEAIGzgp0aZ2W9+v96ujmBcQHoC
27
+ buy0iU68MVj2VlxMyfr1KPZIh1OyhU4UO4zrkREcH8ML70v9cYHNvOd9oynRHnvC
28
+ l2tj/fD3YJ0AEkJxGrYwRWQmvMfC4bJ02bC1+rVOUIXXKp3+cUmiN4sTniof8VFo
29
+ bo/YYP4c7erpERa+9hrqygg6WQbJlk2YRlH3JXPFjmu869i2dcbR5ZLOAeEy+axH
30
+ E4oJcnPkJAr0rw504JGtlZtONZQblwmRJOIdXzolaE3NRGUzGVOUSptZppAKiavY
31
+ fO6tdKQc/5RfA8oQEkg8hrxA5PQSz4TOFJGLpFvIapEk6tMruQ0bHgkhr9auXg==
32
+ -----END CERTIFICATE-----
33
+ date: 2016-11-10 00:00:00.000000000 Z
34
+ dependencies:
35
+ - !ruby/object:Gem::Dependency
36
+ name: hoe
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: '3.15'
42
+ type: :development
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ~>
47
+ - !ruby/object:Gem::Version
48
+ version: '3.15'
49
+ description: |-
50
+ Ruby's contemporary test coverage tools all lie, exaggerating coverage
51
+ through false-positives and creating a false sense of security;
52
+ minitest-coverage tries to address this.
53
+
54
+ Coverage Analysis Tools rely on tracing facilities built into ruby’s
55
+ VM. You run your tests, and collect data. Seems simple, but that’s a
56
+ very flawed approach that buffers your coverage numbers up falsely.
57
+ I’ve witnessed false coverage by as much as 60%, but it could be even
58
+ worse. Worse, the tracing facilities currently make it impossible to
59
+ get truly accurate numbers. Even so, they can be improved to be much
60
+ more accurate.
61
+ email:
62
+ - ryand-ruby@zenspider.com
63
+ executables:
64
+ - minitest_coverage
65
+ - minitest_coverage_baseline
66
+ - minitest_coverage_issues
67
+ - minitest_coverage_report
68
+ extensions: []
69
+ extra_rdoc_files:
70
+ - History.rdoc
71
+ - Manifest.txt
72
+ - README.rdoc
73
+ files:
74
+ - .autotest
75
+ - History.rdoc
76
+ - Manifest.txt
77
+ - README.rdoc
78
+ - Rakefile
79
+ - add_coverage_result_set.patch
80
+ - bin/minitest_coverage
81
+ - bin/minitest_coverage_baseline
82
+ - bin/minitest_coverage_issues
83
+ - bin/minitest_coverage_report
84
+ - example/lib/example.rb
85
+ - example/lib/indirect.rb
86
+ - example/test/test_example.rb
87
+ - example/test/test_indirect.rb
88
+ - lib/coverage/dumper.rb
89
+ - lib/coverage/pruner.rb
90
+ - lib/coverage/start.rb
91
+ - lib/minitest/coverage.rb
92
+ - lib/minitest/coverage_plugin.rb
93
+ - minitest-coverage.el
94
+ - test/minitest/test_coverage.rb
95
+ homepage: https://github.com/seattlerb/minitest-coverage
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options:
101
+ - --main
102
+ - README.rdoc
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - '>'
113
+ - !ruby/object:Gem::Version
114
+ version: 1.3.1
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 2.4.5
118
+ signing_key:
119
+ specification_version: 4
120
+ summary: Ruby's contemporary test coverage tools all lie, exaggerating coverage through
121
+ false-positives and creating a false sense of security; minitest-coverage tries
122
+ to address this
123
+ test_files: []
metadata.gz.sig ADDED
Binary file