simplecov 0.22.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +173 -875
- data/exe/simplecov +8 -0
- data/lib/minitest/simplecov_plugin.rb +18 -7
- data/lib/simplecov/atomic_file.rb +67 -0
- data/lib/simplecov/autostart.rb +9 -0
- data/lib/simplecov/baseline/parser.rb +58 -0
- data/lib/simplecov/baseline.rb +170 -0
- data/lib/simplecov/cli/affected/changed_files.rb +57 -0
- data/lib/simplecov/cli/affected/selection.rb +117 -0
- data/lib/simplecov/cli/affected.rb +148 -0
- data/lib/simplecov/cli/annotations.rb +166 -0
- data/lib/simplecov/cli/badge/svg.rb +70 -0
- data/lib/simplecov/cli/badge.rb +62 -0
- data/lib/simplecov/cli/clean.rb +86 -0
- data/lib/simplecov/cli/command_helpers.rb +91 -0
- data/lib/simplecov/cli/completions/scripts.rb +114 -0
- data/lib/simplecov/cli/completions.rb +83 -0
- data/lib/simplecov/cli/coverage.rb +83 -0
- data/lib/simplecov/cli/coverage_file.rb +109 -0
- data/lib/simplecov/cli/dead_code/output.rb +100 -0
- data/lib/simplecov/cli/dead_code.rb +139 -0
- data/lib/simplecov/cli/diff/output.rb +45 -0
- data/lib/simplecov/cli/diff.rb +115 -0
- data/lib/simplecov/cli/dotfile.rb +156 -0
- data/lib/simplecov/cli/git.rb +41 -0
- data/lib/simplecov/cli/history/output.rb +135 -0
- data/lib/simplecov/cli/history.rb +67 -0
- data/lib/simplecov/cli/merge.rb +115 -0
- data/lib/simplecov/cli/open.rb +45 -0
- data/lib/simplecov/cli/patch/changed_lines.rb +149 -0
- data/lib/simplecov/cli/patch/output.rb +151 -0
- data/lib/simplecov/cli/patch.rb +175 -0
- data/lib/simplecov/cli/ratchet/output.rb +44 -0
- data/lib/simplecov/cli/ratchet.rb +83 -0
- data/lib/simplecov/cli/report.rb +91 -0
- data/lib/simplecov/cli/run.rb +35 -0
- data/lib/simplecov/cli/serve/report_preparer.rb +30 -0
- data/lib/simplecov/cli/serve/static_file_handler.rb +128 -0
- data/lib/simplecov/cli/serve.rb +88 -0
- data/lib/simplecov/cli/show/annotator.rb +87 -0
- data/lib/simplecov/cli/show/sweep.rb +36 -0
- data/lib/simplecov/cli/show.rb +133 -0
- data/lib/simplecov/cli/status/facts.rb +87 -0
- data/lib/simplecov/cli/status.rb +93 -0
- data/lib/simplecov/cli/tests/redundancy.rb +78 -0
- data/lib/simplecov/cli/tests.rb +148 -0
- data/lib/simplecov/cli/uncovered/misses.rb +33 -0
- data/lib/simplecov/cli/uncovered.rb +127 -0
- data/lib/simplecov/cli/usage.rb +153 -0
- data/lib/simplecov/cli/watch/live_report.rb +73 -0
- data/lib/simplecov/cli/watch/narrator.rb +55 -0
- data/lib/simplecov/cli/watch/poller.rb +45 -0
- data/lib/simplecov/cli/watch/session.rb +134 -0
- data/lib/simplecov/cli/watch/test_plan.rb +43 -0
- data/lib/simplecov/cli/watch.rb +85 -0
- data/lib/simplecov/cli.rb +114 -0
- data/lib/simplecov/color.rb +65 -0
- data/lib/simplecov/combine/branches_combiner.rb +44 -21
- data/lib/simplecov/combine/coverage_accumulator.rb +175 -0
- data/lib/simplecov/combine/identity_interner.rb +27 -0
- data/lib/simplecov/combine/interned_counts.rb +28 -0
- data/lib/simplecov/combine/lines_combiner.rb +35 -29
- data/lib/simplecov/combine/methods_combiner.rb +48 -0
- data/lib/simplecov/combine/results_combiner.rb +9 -49
- data/lib/simplecov/combine.rb +0 -24
- data/lib/simplecov/command_guesser.rb +99 -42
- data/lib/simplecov/configuration/baseline.rb +31 -0
- data/lib/simplecov/configuration/coverage.rb +184 -0
- data/lib/simplecov/configuration/coverage_criteria.rb +143 -0
- data/lib/simplecov/configuration/deprecations.rb +21 -0
- data/lib/simplecov/configuration/eval_coverage.rb +37 -0
- data/lib/simplecov/configuration/filters.rb +131 -0
- data/lib/simplecov/configuration/formatting.rb +129 -0
- data/lib/simplecov/configuration/groups.rb +48 -0
- data/lib/simplecov/configuration/history.rb +44 -0
- data/lib/simplecov/configuration/ignored_entries.rb +72 -0
- data/lib/simplecov/configuration/merging.rb +197 -0
- data/lib/simplecov/configuration/missed_caps.rb +51 -0
- data/lib/simplecov/configuration/production.rb +23 -0
- data/lib/simplecov/configuration/test_tracking.rb +48 -0
- data/lib/simplecov/configuration/thresholds.rb +150 -0
- data/lib/simplecov/configuration/view_coverage.rb +37 -0
- data/lib/simplecov/configuration.rb +100 -443
- data/lib/simplecov/configuration_error.rb +5 -0
- data/lib/simplecov/context_map/union.rb +81 -0
- data/lib/simplecov/context_map.rb +187 -0
- data/lib/simplecov/coverage_json.rb +21 -0
- data/lib/simplecov/coverage_statistics.rb +24 -28
- data/lib/simplecov/coverage_violations.rb +254 -0
- data/lib/simplecov/current_run.rb +61 -0
- data/lib/simplecov/defaults.rb +20 -28
- data/lib/simplecov/deprecation.rb +63 -0
- data/lib/simplecov/directive/erb.rb +44 -0
- data/lib/simplecov/directive/haml.rb +33 -0
- data/lib/simplecov/directive/indented_template.rb +37 -0
- data/lib/simplecov/directive/slim.rb +35 -0
- data/lib/simplecov/directive/template.rb +29 -0
- data/lib/simplecov/directive.rb +152 -0
- data/lib/simplecov/exit_codes/baseline_check.rb +46 -0
- data/lib/simplecov/exit_codes/check.rb +39 -0
- data/lib/simplecov/exit_codes/exit_code_handling.rb +24 -5
- data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +17 -67
- data/lib/simplecov/exit_codes/maximum_missed_check.rb +26 -0
- data/lib/simplecov/exit_codes/maximum_missed_per_file_check.rb +34 -0
- data/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +27 -0
- data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +20 -38
- data/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +28 -0
- data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +37 -34
- data/lib/simplecov/exit_codes.rb +26 -0
- data/lib/simplecov/exit_handling.rb +163 -0
- data/lib/simplecov/file_list.rb +63 -48
- data/lib/simplecov/filter.rb +98 -42
- data/lib/simplecov/formatter/base.rb +100 -0
- data/lib/simplecov/formatter/baseline_formatter.rb +98 -0
- data/lib/simplecov/formatter/coverage_json_writer.rb +95 -0
- data/lib/simplecov/formatter/html_formatter/public/index.html +93 -0
- data/lib/simplecov/formatter/html_formatter/viewer_data_validator.rb +153 -0
- data/lib/simplecov/formatter/html_formatter.rb +88 -0
- data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +122 -0
- data/lib/simplecov/formatter/json_formatter/production_section_formatter.rb +48 -0
- data/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +132 -0
- data/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +97 -0
- data/lib/simplecov/formatter/json_formatter.rb +40 -0
- data/lib/simplecov/formatter/multi_formatter.rb +8 -10
- data/lib/simplecov/formatter/simple_formatter.rb +12 -15
- data/lib/simplecov/formatter.rb +21 -1
- data/lib/simplecov/group_names.rb +33 -0
- data/lib/simplecov/history.rb +115 -0
- data/lib/simplecov/last_run.rb +16 -5
- data/lib/simplecov/lines_classifier.rb +67 -19
- data/lib/simplecov/load_global_config.rb +12 -4
- data/lib/simplecov/parallel_adapters/base.rb +50 -0
- data/lib/simplecov/parallel_adapters/generic.rb +33 -0
- data/lib/simplecov/parallel_adapters/parallel_tests.rb +72 -0
- data/lib/simplecov/parallel_adapters.rb +54 -0
- data/lib/simplecov/parallel_coordination.rb +124 -0
- data/lib/simplecov/parallel_result_merger/worker_payload.rb +33 -0
- data/lib/simplecov/parallel_result_merger.rb +171 -0
- data/lib/simplecov/process.rb +34 -12
- data/lib/simplecov/production/error.rb +11 -0
- data/lib/simplecov/production/file_sink.rb +130 -0
- data/lib/simplecov/production.rb +249 -0
- data/lib/simplecov/profiles/bundler_filter.rb +1 -1
- data/lib/simplecov/profiles/hidden_filter.rb +1 -1
- data/lib/simplecov/profiles/rails.rb +13 -10
- data/lib/simplecov/profiles/root_filter.rb +2 -5
- data/lib/simplecov/profiles/strict.rb +22 -0
- data/lib/simplecov/profiles/test_frameworks.rb +1 -4
- data/lib/simplecov/profiles.rb +26 -19
- data/lib/simplecov/report_deferral.rb +45 -0
- data/lib/simplecov/report_stamp.rb +25 -0
- data/lib/simplecov/result/filter_config.rb +19 -0
- data/lib/simplecov/result/missing_source_files_reporter.rb +48 -0
- data/lib/simplecov/result/serialization.rb +43 -0
- data/lib/simplecov/result/source_file_builder.rb +46 -0
- data/lib/simplecov/result.rb +123 -47
- data/lib/simplecov/result_adapter.rb +130 -11
- data/lib/simplecov/result_merger/contexts.rb +22 -0
- data/lib/simplecov/result_merger/legacy_format_adapter.rb +24 -0
- data/lib/simplecov/result_merger/resultset_file.rb +67 -0
- data/lib/simplecov/result_merger/resultset_run_identity.rb +65 -0
- data/lib/simplecov/result_merger/resultset_store.rb +62 -0
- data/lib/simplecov/result_merger/unloaded_files.rb +95 -0
- data/lib/simplecov/result_merger.rb +120 -124
- data/lib/simplecov/result_processing.rb +188 -0
- data/lib/simplecov/run_identity.rb +75 -0
- data/lib/simplecov/simulate_coverage.rb +72 -17
- data/lib/simplecov/source_file/branch.rb +8 -35
- data/lib/simplecov/source_file/branch_builder.rb +95 -0
- data/lib/simplecov/source_file/builder_context.rb +28 -0
- data/lib/simplecov/source_file/line.rb +17 -32
- data/lib/simplecov/source_file/line_builder.rb +37 -0
- data/lib/simplecov/source_file/method.rb +54 -0
- data/lib/simplecov/source_file/method_builder.rb +51 -0
- data/lib/simplecov/source_file/ruby_data_parser.rb +103 -0
- data/lib/simplecov/source_file/skip_chunks.rb +72 -0
- data/lib/simplecov/source_file/source_loader.rb +89 -0
- data/lib/simplecov/source_file/statistics.rb +76 -0
- data/lib/simplecov/source_file.rb +64 -260
- data/lib/simplecov/static_coverage_extractor/condition_folding.rb +155 -0
- data/lib/simplecov/static_coverage_extractor/location_conventions.rb +191 -0
- data/lib/simplecov/static_coverage_extractor/method_collector.rb +45 -0
- data/lib/simplecov/static_coverage_extractor/prism_compat.rb +46 -0
- data/lib/simplecov/static_coverage_extractor/value_position.rb +61 -0
- data/lib/simplecov/static_coverage_extractor/visitor.rb +163 -0
- data/lib/simplecov/static_coverage_extractor.rb +78 -0
- data/lib/simplecov/test_tracker/accessors.rb +34 -0
- data/lib/simplecov/test_tracker/constant_watch.rb +49 -0
- data/lib/simplecov/test_tracker/delta.rb +69 -0
- data/lib/simplecov/test_tracker/framework_hooks.rb +130 -0
- data/lib/simplecov/test_tracker.rb +162 -0
- data/lib/simplecov/unloaded_file_injector.rb +62 -0
- data/lib/simplecov/useless_results_remover.rb +17 -7
- data/lib/simplecov/version.rb +1 -1
- data/lib/simplecov/view_coverage/template_compiler.rb +83 -0
- data/lib/simplecov/view_coverage.rb +55 -0
- data/lib/simplecov-html.rb +5 -0
- data/lib/simplecov.rb +143 -394
- data/lib/simplecov_json_formatter.rb +5 -0
- data/man/simplecov.1 +354 -0
- data/sig/simplecov.rbs +1710 -0
- metadata +183 -61
- data/CHANGELOG.md +0 -191
- data/doc/alternate-formatters.md +0 -71
- data/doc/commercial-services.md +0 -25
- data/doc/editor-integration.md +0 -18
- data/lib/simplecov/combine/files_combiner.rb +0 -24
- data/lib/simplecov/default_formatter.rb +0 -20
|
@@ -1,500 +1,157 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "fileutils"
|
|
4
|
-
require "docile"
|
|
5
|
-
require_relative "formatter/multi_formatter"
|
|
6
4
|
|
|
7
5
|
module SimpleCov
|
|
8
|
-
#
|
|
9
|
-
# Bundles the configuration options used for SimpleCov. All methods
|
|
10
|
-
# defined here are usable from SimpleCov directly. Please check out
|
|
11
|
-
# SimpleCov documentation for further info.
|
|
12
|
-
#
|
|
13
6
|
module Configuration
|
|
14
|
-
attr_writer :filters, :groups, :formatter, :print_error_status
|
|
15
|
-
|
|
16
|
-
#
|
|
17
|
-
# The root for the project. This defaults to the
|
|
18
|
-
# current working directory.
|
|
19
|
-
#
|
|
20
|
-
# Configure with SimpleCov.root('/my/project/path')
|
|
21
|
-
#
|
|
22
7
|
def root(root = nil)
|
|
23
|
-
return @root if
|
|
24
|
-
|
|
25
|
-
@coverage_path = nil # invalidate cache
|
|
26
|
-
@root = File.expand_path(root || Dir.getwd)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
#
|
|
30
|
-
# The name of the output and cache directory. Defaults to 'coverage'
|
|
31
|
-
#
|
|
32
|
-
# Configure with SimpleCov.coverage_dir('cov')
|
|
33
|
-
#
|
|
34
|
-
def coverage_dir(dir = nil)
|
|
35
|
-
return @coverage_dir if defined?(@coverage_dir) && dir.nil?
|
|
8
|
+
return @root if instance_variable_defined?(:@root) && root.nil?
|
|
36
9
|
|
|
37
|
-
|
|
38
|
-
@
|
|
10
|
+
self.root = root
|
|
11
|
+
@root
|
|
39
12
|
end
|
|
40
13
|
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
def coverage_path
|
|
47
|
-
@coverage_path ||= begin
|
|
48
|
-
coverage_path = File.expand_path(coverage_dir, root)
|
|
49
|
-
FileUtils.mkdir_p coverage_path
|
|
50
|
-
coverage_path
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
#
|
|
55
|
-
# Coverage results will always include files matched by this glob, whether
|
|
56
|
-
# or not they were explicitly required. Without this, un-required files
|
|
57
|
-
# will not be present in the final report.
|
|
58
|
-
#
|
|
59
|
-
def track_files(glob)
|
|
60
|
-
@tracked_files = glob
|
|
14
|
+
# nil means the working directory, the default the reader would have derived.
|
|
15
|
+
def root=(root)
|
|
16
|
+
@coverage_path = nil unless @coverage_path_explicit # invalidate cache
|
|
17
|
+
@root = File.expand_path(root || Dir.getwd)
|
|
61
18
|
end
|
|
62
19
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
# explicitly required.
|
|
66
|
-
#
|
|
67
|
-
def tracked_files
|
|
68
|
-
@tracked_files if defined?(@tracked_files)
|
|
69
|
-
end
|
|
20
|
+
def coverage_dir(dir = nil)
|
|
21
|
+
return @coverage_dir if instance_variable_defined?(:@coverage_dir) && dir.nil?
|
|
70
22
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
#
|
|
74
|
-
def filters
|
|
75
|
-
@filters ||= []
|
|
23
|
+
self.coverage_dir = dir
|
|
24
|
+
@coverage_dir
|
|
76
25
|
end
|
|
77
26
|
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
#
|
|
85
|
-
# You can specify it manually with SimpleCov.command_name("test:units") - please
|
|
86
|
-
# also check out the corresponding section in README.rdoc
|
|
87
|
-
def command_name(name = nil)
|
|
88
|
-
@name = name unless name.nil?
|
|
89
|
-
@name ||= SimpleCov::CommandGuesser.guess
|
|
90
|
-
@name
|
|
27
|
+
# nil means the default 'coverage', recorded as a derivation rather than a
|
|
28
|
+
# choice.
|
|
29
|
+
def coverage_dir=(dir)
|
|
30
|
+
@coverage_path = nil unless @coverage_path_explicit # invalidate cache
|
|
31
|
+
@coverage_dir_explicit = true unless dir.nil?
|
|
32
|
+
@coverage_dir = dir || "coverage"
|
|
91
33
|
end
|
|
92
34
|
|
|
93
35
|
#
|
|
94
|
-
#
|
|
36
|
+
# Defaults to `SimpleCov.root` + `SimpleCov.coverage_dir`, but callers can
|
|
37
|
+
# override with an arbitrary absolute path, handy for out-of-tree build
|
|
38
|
+
# directories (#716).
|
|
95
39
|
#
|
|
96
|
-
#
|
|
40
|
+
# Reading is pure: the directory is only created when a path is explicitly
|
|
41
|
+
# assigned. The codepaths that write into it ensure existence themselves,
|
|
42
|
+
# so read-only CLI subcommands that interpolate the path into status text
|
|
43
|
+
# don't materialize a stray `coverage/` directory.
|
|
97
44
|
#
|
|
98
|
-
def
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
@formatter = formatter
|
|
102
|
-
raise "No formatter configured. Please specify a formatter using SimpleCov.formatter = SimpleCov::Formatter::SimpleFormatter" unless @formatter
|
|
45
|
+
def coverage_path(path = nil)
|
|
46
|
+
self.coverage_path = path if path
|
|
103
47
|
|
|
104
|
-
@
|
|
48
|
+
@coverage_path ||= File.expand_path(coverage_dir, root)
|
|
105
49
|
end
|
|
106
50
|
|
|
107
|
-
#
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
@
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
#
|
|
115
|
-
# Gets the configured formatters.
|
|
116
|
-
#
|
|
117
|
-
def formatters
|
|
118
|
-
if @formatter.is_a?(SimpleCov::Formatter::MultiFormatter)
|
|
119
|
-
@formatter.formatters
|
|
120
|
-
else
|
|
121
|
-
Array(formatter)
|
|
122
|
-
end
|
|
51
|
+
# Assigning is the signal the caller intends to write there, so the
|
|
52
|
+
# directory is created.
|
|
53
|
+
def coverage_path=(path)
|
|
54
|
+
expanded = File.expand_path(path)
|
|
55
|
+
@coverage_path = expanded
|
|
56
|
+
@coverage_path_explicit = true
|
|
57
|
+
FileUtils.mkdir_p expanded
|
|
123
58
|
end
|
|
124
59
|
|
|
125
60
|
#
|
|
126
|
-
#
|
|
127
|
-
#
|
|
61
|
+
# The name of the command (a.k.a. Test Suite) currently running. Used for
|
|
62
|
+
# result merging and caching. Auto-detected.
|
|
128
63
|
#
|
|
129
|
-
def
|
|
130
|
-
|
|
64
|
+
def command_name(name = nil)
|
|
65
|
+
self.command_name = name unless name.nil?
|
|
66
|
+
@command_name ||= CommandGuesser.guess
|
|
131
67
|
end
|
|
132
68
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
# the coverage metrics by wrapping it inside # :nocov: comment blocks. The nocov token
|
|
136
|
-
# can be configured to be any other string using this.
|
|
137
|
-
#
|
|
138
|
-
# Configure with SimpleCov.nocov_token('skip') or it's alias SimpleCov.skip_token('skip')
|
|
139
|
-
#
|
|
140
|
-
def nocov_token(nocov_token = nil)
|
|
141
|
-
return @nocov_token if defined?(@nocov_token) && nocov_token.nil?
|
|
142
|
-
|
|
143
|
-
@nocov_token = (nocov_token || "nocov")
|
|
69
|
+
def command_name=(name)
|
|
70
|
+
@command_name = name
|
|
144
71
|
end
|
|
145
|
-
alias skip_token nocov_token
|
|
146
72
|
|
|
147
|
-
#
|
|
148
|
-
# Returns the configured groups. Add groups using SimpleCov.add_group
|
|
149
|
-
#
|
|
150
|
-
def groups
|
|
151
|
-
@groups ||= {}
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
#
|
|
155
|
-
# Returns the hash of available profiles
|
|
156
|
-
#
|
|
157
73
|
def profiles
|
|
158
|
-
@profiles ||=
|
|
74
|
+
@profiles ||= Profiles.new
|
|
159
75
|
end
|
|
160
76
|
|
|
161
|
-
def adapters
|
|
162
|
-
warn "#{Kernel.caller.first}: [DEPRECATION] #adapters is deprecated. Use #profiles instead."
|
|
163
|
-
profiles
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
#
|
|
167
|
-
# Allows you to configure simplecov in a block instead of prepending SimpleCov to all config methods
|
|
168
|
-
# you're calling.
|
|
169
77
|
#
|
|
170
|
-
#
|
|
171
|
-
#
|
|
172
|
-
#
|
|
173
|
-
#
|
|
174
|
-
# This is equivalent to SimpleCov.add_filter 'foobar' and thus makes it easier to set a bunch of configure
|
|
175
|
-
# options at once.
|
|
78
|
+
# Configure simplecov in a block instead of prepending SimpleCov to each
|
|
79
|
+
# config method. Parameterized blocks retain their caller context and
|
|
80
|
+
# receive this configuration target explicitly.
|
|
176
81
|
#
|
|
177
82
|
def configure(&block)
|
|
178
|
-
|
|
83
|
+
raise ArgumentError, "configuration block required" unless block
|
|
84
|
+
|
|
85
|
+
if block.parameters.empty?
|
|
86
|
+
instance_exec(&(_ = block))
|
|
87
|
+
else
|
|
88
|
+
yield self
|
|
89
|
+
end
|
|
90
|
+
self
|
|
179
91
|
end
|
|
180
92
|
|
|
181
|
-
#
|
|
182
|
-
# Gets or sets the behavior to process coverage results.
|
|
183
|
-
#
|
|
184
|
-
# By default, it will call SimpleCov.result.format!
|
|
185
|
-
#
|
|
186
|
-
# Configure with:
|
|
187
|
-
#
|
|
188
|
-
# SimpleCov.at_exit do
|
|
189
|
-
# puts "Coverage done"
|
|
190
|
-
# SimpleCov.result.format!
|
|
191
|
-
# end
|
|
192
|
-
#
|
|
193
93
|
def at_exit(&block)
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
94
|
+
@at_exit = block if block
|
|
95
|
+
configured = @at_exit
|
|
96
|
+
return configured if configured
|
|
97
|
+
return -> {} unless active_session?
|
|
98
|
+
|
|
99
|
+
@at_exit = lambda do
|
|
100
|
+
result = SimpleCov.result
|
|
101
|
+
result.format! if result && SimpleCov.merge_finalization_owner?
|
|
102
|
+
end
|
|
198
103
|
end
|
|
199
104
|
|
|
200
|
-
#
|
|
201
|
-
#
|
|
202
|
-
def
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
@enable_for_subprocesses = value || false
|
|
105
|
+
# The Coverage module is actively tracking, or a `@result` has already been
|
|
106
|
+
# assembled (`SimpleCov.collate` never starts Coverage).
|
|
107
|
+
def active_session?
|
|
108
|
+
!!SimpleCov.result? || coverage_running?
|
|
206
109
|
end
|
|
207
110
|
|
|
208
|
-
#
|
|
209
|
-
|
|
210
|
-
|
|
111
|
+
# A configuration loaded on its own may have no Coverage to ask, which is
|
|
112
|
+
# not something a suite that measures coverage can be.
|
|
113
|
+
def coverage_running?
|
|
114
|
+
defined?(Coverage) ? Coverage.running? : false
|
|
211
115
|
end
|
|
212
116
|
|
|
213
|
-
#
|
|
214
|
-
# Gets or sets the behavior to start a new forked Process.
|
|
215
|
-
#
|
|
216
|
-
# By default, it will add " (Process #{pid})" to the command_name, and start SimpleCov in quiet mode
|
|
217
|
-
#
|
|
218
|
-
# Configure with:
|
|
219
|
-
#
|
|
220
|
-
# SimpleCov.at_fork do |pid|
|
|
221
|
-
# SimpleCov.start do
|
|
222
|
-
# # This needs a unique name so it won't be ovewritten
|
|
223
|
-
# SimpleCov.command_name "#{SimpleCov.command_name} (subprocess: #{pid})"
|
|
224
|
-
# # be quiet, the parent process will be in charge of using the regular formatter and checking coverage totals
|
|
225
|
-
# SimpleCov.print_error_status = false
|
|
226
|
-
# SimpleCov.formatter SimpleCov::Formatter::SimpleFormatter
|
|
227
|
-
# SimpleCov.minimum_coverage 0
|
|
228
|
-
# # start
|
|
229
|
-
# SimpleCov.start
|
|
230
|
-
# end
|
|
231
|
-
# end
|
|
232
|
-
#
|
|
233
117
|
def at_fork(&block)
|
|
234
|
-
@at_fork = block if
|
|
235
|
-
@at_fork ||= lambda { |
|
|
236
|
-
#
|
|
237
|
-
|
|
238
|
-
#
|
|
239
|
-
|
|
240
|
-
|
|
118
|
+
@at_fork = block if block
|
|
119
|
+
@at_fork ||= lambda { |_pid|
|
|
120
|
+
# Needs a name that's unique per worker within a run yet identical across
|
|
121
|
+
# runs. Built from SimpleCov's stable fork serial rather than the OS pid:
|
|
122
|
+
# with the pid, every run produced uniquely-named results that never
|
|
123
|
+
# overwrote the previous run's, so they piled up in .resultset.json
|
|
124
|
+
# until merge_timeout and the merged report's file set drifted from run
|
|
125
|
+
# to run (#1171).
|
|
126
|
+
SimpleCov.command_name "#{SimpleCov.command_name} (subprocess: #{SimpleCov.subprocess_serial})"
|
|
127
|
+
SimpleCov.print_errors false
|
|
128
|
+
SimpleCov.formatter Formatter::SimpleFormatter
|
|
241
129
|
SimpleCov.minimum_coverage 0
|
|
242
|
-
# start
|
|
243
130
|
SimpleCov.start
|
|
244
131
|
}
|
|
245
132
|
end
|
|
246
133
|
|
|
247
|
-
#
|
|
248
|
-
# Returns the project name - currently assuming the last dirname in
|
|
249
|
-
# the SimpleCov.root is this.
|
|
250
|
-
#
|
|
134
|
+
# Only a String renames, and a name already chosen survives anything else.
|
|
251
135
|
def project_name(new_name = nil)
|
|
252
|
-
return @project_name if defined?(@project_name) && @project_name && new_name.nil?
|
|
253
|
-
|
|
254
136
|
@project_name = new_name if new_name.is_a?(String)
|
|
255
|
-
@project_name ||= File.basename(root
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
#
|
|
259
|
-
# Defines whether to use result merging so all your test suites (test:units, test:functionals, cucumber, ...)
|
|
260
|
-
# are joined and combined into a single coverage report
|
|
261
|
-
#
|
|
262
|
-
def use_merging(use = nil)
|
|
263
|
-
@use_merging = use unless use.nil?
|
|
264
|
-
@use_merging = true unless defined?(@use_merging) && @use_merging == false
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
#
|
|
268
|
-
# Defines the maximum age (in seconds) of a resultset to still be included in merged results.
|
|
269
|
-
# i.e. If you run cucumber features, then later rake test, if the stored cucumber resultset is
|
|
270
|
-
# more seconds ago than specified here, it won't be taken into account when merging (and is also
|
|
271
|
-
# purged from the resultset cache)
|
|
272
|
-
#
|
|
273
|
-
# Of course, this only applies when merging is active (e.g. SimpleCov.use_merging is not false!)
|
|
274
|
-
#
|
|
275
|
-
# Default is 600 seconds (10 minutes)
|
|
276
|
-
#
|
|
277
|
-
# Configure with SimpleCov.merge_timeout(3600) # 1hr
|
|
278
|
-
#
|
|
279
|
-
def merge_timeout(seconds = nil)
|
|
280
|
-
@merge_timeout = seconds if seconds.is_a?(Integer)
|
|
281
|
-
@merge_timeout ||= 600
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
#
|
|
285
|
-
# Defines the minimum overall coverage required for the testsuite to pass.
|
|
286
|
-
# SimpleCov will return non-zero if the current coverage is below this threshold.
|
|
287
|
-
#
|
|
288
|
-
# Default is 0% (disabled)
|
|
289
|
-
#
|
|
290
|
-
def minimum_coverage(coverage = nil)
|
|
291
|
-
return @minimum_coverage ||= {} unless coverage
|
|
292
|
-
|
|
293
|
-
coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
|
|
294
|
-
|
|
295
|
-
raise_on_invalid_coverage(coverage, "minimum_coverage")
|
|
296
|
-
|
|
297
|
-
@minimum_coverage = coverage
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
def raise_on_invalid_coverage(coverage, coverage_setting)
|
|
301
|
-
coverage.each_key { |criterion| raise_if_criterion_disabled(criterion) }
|
|
302
|
-
coverage.each_value do |percent|
|
|
303
|
-
minimum_possible_coverage_exceeded(coverage_setting) if percent && percent > 100
|
|
304
|
-
end
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
#
|
|
308
|
-
# Defines the maximum coverage drop at once allowed for the testsuite to pass.
|
|
309
|
-
# SimpleCov will return non-zero if the coverage decreases by more than this threshold.
|
|
310
|
-
#
|
|
311
|
-
# Default is 100% (disabled)
|
|
312
|
-
#
|
|
313
|
-
def maximum_coverage_drop(coverage_drop = nil)
|
|
314
|
-
return @maximum_coverage_drop ||= {} unless coverage_drop
|
|
315
|
-
|
|
316
|
-
coverage_drop = {primary_coverage => coverage_drop} if coverage_drop.is_a?(Numeric)
|
|
317
|
-
|
|
318
|
-
raise_on_invalid_coverage(coverage_drop, "maximum_coverage_drop")
|
|
319
|
-
|
|
320
|
-
@maximum_coverage_drop = coverage_drop
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
#
|
|
324
|
-
# Defines the minimum coverage per file required for the testsuite to pass.
|
|
325
|
-
# SimpleCov will return non-zero if the current coverage of the least covered file
|
|
326
|
-
# is below this threshold.
|
|
327
|
-
#
|
|
328
|
-
# Default is 0% (disabled)
|
|
329
|
-
#
|
|
330
|
-
def minimum_coverage_by_file(coverage = nil)
|
|
331
|
-
return @minimum_coverage_by_file ||= {} unless coverage
|
|
332
|
-
|
|
333
|
-
coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
|
|
334
|
-
|
|
335
|
-
raise_on_invalid_coverage(coverage, "minimum_coverage_by_file")
|
|
336
|
-
|
|
337
|
-
@minimum_coverage_by_file = coverage
|
|
338
|
-
end
|
|
339
|
-
|
|
340
|
-
#
|
|
341
|
-
# Refuses any coverage drop. That is, coverage is only allowed to increase.
|
|
342
|
-
# SimpleCov will return non-zero if the coverage decreases.
|
|
343
|
-
#
|
|
344
|
-
def refuse_coverage_drop(*criteria)
|
|
345
|
-
criteria = coverage_criteria if criteria.empty?
|
|
346
|
-
|
|
347
|
-
maximum_coverage_drop(criteria.map { |c| [c, 0] }.to_h)
|
|
348
|
-
end
|
|
349
|
-
|
|
350
|
-
#
|
|
351
|
-
# Add a filter to the processing chain.
|
|
352
|
-
# There are four ways to define a filter:
|
|
353
|
-
#
|
|
354
|
-
# * as a String that will then be matched against all source files' file paths,
|
|
355
|
-
# SimpleCov.add_filter 'app/models' # will reject all your models
|
|
356
|
-
# * as a block which will be passed the source file in question and should either
|
|
357
|
-
# return a true or false value, depending on whether the file should be removed
|
|
358
|
-
# SimpleCov.add_filter do |src_file|
|
|
359
|
-
# File.basename(src_file.filename) == 'environment.rb'
|
|
360
|
-
# end # Will exclude environment.rb files from the results
|
|
361
|
-
# * as an array of strings that are matched against all sorce files' file
|
|
362
|
-
# paths and then ignored (basically string filter multiple times)
|
|
363
|
-
# SimpleCov.add_filter ['app/models', 'app/helpers'] # ignores both dirs
|
|
364
|
-
# * as an instance of a subclass of SimpleCov::Filter. See the documentation there
|
|
365
|
-
# on how to define your own filter classes
|
|
366
|
-
#
|
|
367
|
-
def add_filter(filter_argument = nil, &filter_proc)
|
|
368
|
-
filters << parse_filter(filter_argument, &filter_proc)
|
|
369
|
-
end
|
|
370
|
-
|
|
371
|
-
#
|
|
372
|
-
# Define a group for files. Works similar to add_filter, only that the first
|
|
373
|
-
# argument is the desired group name and files PASSING the filter end up in the group
|
|
374
|
-
# (while filters exclude when the filter is applicable).
|
|
375
|
-
#
|
|
376
|
-
def add_group(group_name, filter_argument = nil, &filter_proc)
|
|
377
|
-
groups[group_name] = parse_filter(filter_argument, &filter_proc)
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
SUPPORTED_COVERAGE_CRITERIA = %i[line branch].freeze
|
|
381
|
-
DEFAULT_COVERAGE_CRITERION = :line
|
|
382
|
-
#
|
|
383
|
-
# Define which coverage criterion should be evaluated.
|
|
384
|
-
#
|
|
385
|
-
# Possible coverage criteria:
|
|
386
|
-
# * :line - coverage based on lines aka has this line been executed?
|
|
387
|
-
# * :branch - coverage based on branches aka has this branch (think conditions) been executed?
|
|
388
|
-
#
|
|
389
|
-
# If not set the default is `:line`
|
|
390
|
-
#
|
|
391
|
-
# @param [Symbol] criterion
|
|
392
|
-
#
|
|
393
|
-
def coverage_criterion(criterion = nil)
|
|
394
|
-
return @coverage_criterion ||= primary_coverage unless criterion
|
|
395
|
-
|
|
396
|
-
raise_if_criterion_unsupported(criterion)
|
|
397
|
-
|
|
398
|
-
@coverage_criterion = criterion
|
|
399
|
-
end
|
|
400
|
-
|
|
401
|
-
def enable_coverage(criterion)
|
|
402
|
-
raise_if_criterion_unsupported(criterion)
|
|
403
|
-
|
|
404
|
-
coverage_criteria << criterion
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
def primary_coverage(criterion = nil)
|
|
408
|
-
if criterion.nil?
|
|
409
|
-
@primary_coverage ||= DEFAULT_COVERAGE_CRITERION
|
|
410
|
-
else
|
|
411
|
-
raise_if_criterion_disabled(criterion)
|
|
412
|
-
@primary_coverage = criterion
|
|
413
|
-
end
|
|
414
|
-
end
|
|
415
|
-
|
|
416
|
-
def coverage_criteria
|
|
417
|
-
@coverage_criteria ||= Set[primary_coverage]
|
|
418
|
-
end
|
|
419
|
-
|
|
420
|
-
def coverage_criterion_enabled?(criterion)
|
|
421
|
-
coverage_criteria.member?(criterion)
|
|
422
|
-
end
|
|
423
|
-
|
|
424
|
-
def clear_coverage_criteria
|
|
425
|
-
@coverage_criteria = nil
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
def branch_coverage?
|
|
429
|
-
branch_coverage_supported? && coverage_criterion_enabled?(:branch)
|
|
430
|
-
end
|
|
431
|
-
|
|
432
|
-
def coverage_start_arguments_supported?
|
|
433
|
-
# safe to cache as within one process this value should never
|
|
434
|
-
# change
|
|
435
|
-
return @coverage_start_arguments_supported if defined?(@coverage_start_arguments_supported)
|
|
436
|
-
|
|
437
|
-
@coverage_start_arguments_supported = begin
|
|
438
|
-
require "coverage"
|
|
439
|
-
!Coverage.method(:start).arity.zero?
|
|
440
|
-
end
|
|
441
|
-
end
|
|
442
|
-
|
|
443
|
-
def branch_coverage_supported?
|
|
444
|
-
coverage_start_arguments_supported? && RUBY_ENGINE != "jruby"
|
|
445
|
-
end
|
|
446
|
-
|
|
447
|
-
def coverage_for_eval_supported?
|
|
448
|
-
require "coverage"
|
|
449
|
-
defined?(Coverage.supported?) && Coverage.supported?(:eval)
|
|
450
|
-
end
|
|
451
|
-
|
|
452
|
-
def coverage_for_eval_enabled?
|
|
453
|
-
@coverage_for_eval_enabled ||= false
|
|
454
|
-
end
|
|
455
|
-
|
|
456
|
-
def enable_coverage_for_eval
|
|
457
|
-
if coverage_for_eval_supported?
|
|
458
|
-
@coverage_for_eval_enabled = true
|
|
459
|
-
else
|
|
460
|
-
warn "Coverage for eval is not available; Use Ruby 3.2.0 or later"
|
|
461
|
-
end
|
|
462
|
-
end
|
|
463
|
-
|
|
464
|
-
private
|
|
465
|
-
|
|
466
|
-
def raise_if_criterion_disabled(criterion)
|
|
467
|
-
raise_if_criterion_unsupported(criterion)
|
|
468
|
-
# rubocop:disable Style/IfUnlessModifier
|
|
469
|
-
unless coverage_criterion_enabled?(criterion)
|
|
470
|
-
raise "Coverage criterion #{criterion}, is disabled! Please enable it first through enable_coverage #{criterion} (if supported)"
|
|
471
|
-
end
|
|
472
|
-
# rubocop:enable Style/IfUnlessModifier
|
|
473
|
-
end
|
|
474
|
-
|
|
475
|
-
def raise_if_criterion_unsupported(criterion)
|
|
476
|
-
# rubocop:disable Style/IfUnlessModifier
|
|
477
|
-
unless SUPPORTED_COVERAGE_CRITERIA.member?(criterion)
|
|
478
|
-
raise "Unsupported coverage criterion #{criterion}, supported values are #{SUPPORTED_COVERAGE_CRITERIA}"
|
|
479
|
-
end
|
|
480
|
-
# rubocop:enable Style/IfUnlessModifier
|
|
481
|
-
end
|
|
482
|
-
|
|
483
|
-
def minimum_possible_coverage_exceeded(coverage_option)
|
|
484
|
-
warn "The coverage you set for #{coverage_option} is greater than 100%"
|
|
485
|
-
end
|
|
486
|
-
|
|
487
|
-
#
|
|
488
|
-
# The actual filter processor. Not meant for direct use
|
|
489
|
-
#
|
|
490
|
-
def parse_filter(filter_argument = nil, &filter_proc)
|
|
491
|
-
filter = filter_argument || filter_proc
|
|
492
|
-
|
|
493
|
-
if filter
|
|
494
|
-
SimpleCov::Filter.build_filter(filter)
|
|
495
|
-
else
|
|
496
|
-
raise ArgumentError, "Please specify either a filter or a block to filter with"
|
|
497
|
-
end
|
|
137
|
+
@project_name ||= File.basename(root).capitalize.tr("_", " ")
|
|
498
138
|
end
|
|
499
139
|
end
|
|
500
140
|
end
|
|
141
|
+
|
|
142
|
+
require_relative "configuration/coverage"
|
|
143
|
+
require_relative "configuration/coverage_criteria"
|
|
144
|
+
require_relative "configuration/eval_coverage"
|
|
145
|
+
require_relative "configuration/filters"
|
|
146
|
+
require_relative "configuration/groups"
|
|
147
|
+
require_relative "configuration/formatting"
|
|
148
|
+
require_relative "configuration/ignored_entries"
|
|
149
|
+
require_relative "configuration/merging"
|
|
150
|
+
require_relative "configuration/test_tracking"
|
|
151
|
+
require_relative "configuration/thresholds"
|
|
152
|
+
require_relative "configuration/baseline"
|
|
153
|
+
require_relative "configuration/deprecations"
|
|
154
|
+
require_relative "configuration/history"
|
|
155
|
+
require_relative "configuration/missed_caps"
|
|
156
|
+
require_relative "configuration/production"
|
|
157
|
+
require_relative "configuration/view_coverage"
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
class ContextMap
|
|
5
|
+
# Accumulates the context maps of every result a merge absorbs, under the
|
|
6
|
+
# all-or-nothing rule the resultset format needs: the merged result carries
|
|
7
|
+
# the union of the maps when every merged result recorded one, and no map at
|
|
8
|
+
# all otherwise. Keeping a partial union would present one worker's map as
|
|
9
|
+
# the whole run's, silently omitting the tests of the results that didn't
|
|
10
|
+
# record.
|
|
11
|
+
class Union
|
|
12
|
+
attr_reader :carrying, :entries
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@map = ContextMap.new
|
|
16
|
+
@complete = true
|
|
17
|
+
@carrying = 0
|
|
18
|
+
@entries = 0
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def collector
|
|
22
|
+
->(surviving) { absorb_resultset(surviving) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def absorb_resultset(resultset)
|
|
26
|
+
resultset.each_value { |data| absorb_entry(data) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def absorb_entry(data)
|
|
30
|
+
@entries += 1
|
|
31
|
+
map = ContextMap.from_hash(data["contexts"])
|
|
32
|
+
return @complete = false unless map
|
|
33
|
+
|
|
34
|
+
@carrying += 1
|
|
35
|
+
@map.absorb(map)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# The parallel merge builds one union per worker over its slice and ships it
|
|
39
|
+
# back, so the parent combines unions rather than re-reading entries.
|
|
40
|
+
def absorb_union(other)
|
|
41
|
+
@entries += other.entries
|
|
42
|
+
@carrying += other.carrying
|
|
43
|
+
@complete &&= other.complete?
|
|
44
|
+
@map.absorb(other.partial_map)
|
|
45
|
+
self
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def complete?
|
|
49
|
+
@complete
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# The union when every absorbed result carried a map, nil otherwise. Dropping
|
|
53
|
+
# warns when the merge mixed results with and without maps, since that
|
|
54
|
+
# usually means `track_tests` is on in some workers and not others; a merge
|
|
55
|
+
# where nothing recorded stays quiet.
|
|
56
|
+
def map
|
|
57
|
+
return @map if @complete
|
|
58
|
+
|
|
59
|
+
warn_about_partial_maps
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
protected
|
|
63
|
+
|
|
64
|
+
# Protected: only another union folding this one in may read it.
|
|
65
|
+
def partial_map
|
|
66
|
+
@map
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def warn_about_partial_maps
|
|
72
|
+
return unless @carrying.positive? && SimpleCov.print_errors
|
|
73
|
+
|
|
74
|
+
warn "[SimpleCov]: Dropped the per-test map from the merged result: " \
|
|
75
|
+
"only #{@carrying} of #{@entries} merged results carry one. The map is " \
|
|
76
|
+
"kept only when every merged result records it, so enable `track_tests` " \
|
|
77
|
+
"in every suite that should contribute."
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|