ultra-pro-pkg 0.0.1
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 +7 -0
- data/simplecov-1.0.0/LICENSE +20 -0
- data/simplecov-1.0.0/README.md +1524 -0
- data/simplecov-1.0.0/doc/alternate-formatters.md +66 -0
- data/simplecov-1.0.0/doc/commercial-services.md +25 -0
- data/simplecov-1.0.0/doc/editor-integration.md +18 -0
- data/simplecov-1.0.0/exe/simplecov +11 -0
- data/simplecov-1.0.0/lib/minitest/simplecov_plugin.rb +171 -0
- data/simplecov-1.0.0/lib/simplecov/autostart.rb +11 -0
- data/simplecov-1.0.0/lib/simplecov/cli/clean.rb +47 -0
- data/simplecov-1.0.0/lib/simplecov/cli/coverage.rb +91 -0
- data/simplecov-1.0.0/lib/simplecov/cli/diff.rb +151 -0
- data/simplecov-1.0.0/lib/simplecov/cli/dotfile.rb +100 -0
- data/simplecov-1.0.0/lib/simplecov/cli/merge.rb +116 -0
- data/simplecov-1.0.0/lib/simplecov/cli/open.rb +50 -0
- data/simplecov-1.0.0/lib/simplecov/cli/report.rb +84 -0
- data/simplecov-1.0.0/lib/simplecov/cli/run.rb +36 -0
- data/simplecov-1.0.0/lib/simplecov/cli/serve.rb +139 -0
- data/simplecov-1.0.0/lib/simplecov/cli/uncovered.rb +107 -0
- data/simplecov-1.0.0/lib/simplecov/cli.rb +150 -0
- data/simplecov-1.0.0/lib/simplecov/color.rb +74 -0
- data/simplecov-1.0.0/lib/simplecov/combine/branches_combiner.rb +54 -0
- data/simplecov-1.0.0/lib/simplecov/combine/files_combiner.rb +30 -0
- data/simplecov-1.0.0/lib/simplecov/combine/lines_combiner.rb +45 -0
- data/simplecov-1.0.0/lib/simplecov/combine/methods_combiner.rb +26 -0
- data/simplecov-1.0.0/lib/simplecov/combine/results_combiner.rb +61 -0
- data/simplecov-1.0.0/lib/simplecov/combine.rb +30 -0
- data/simplecov-1.0.0/lib/simplecov/command_guesser.rb +78 -0
- data/simplecov-1.0.0/lib/simplecov/configuration/coverage.rb +171 -0
- data/simplecov-1.0.0/lib/simplecov/configuration/coverage_criteria.rb +156 -0
- data/simplecov-1.0.0/lib/simplecov/configuration/filters.rb +197 -0
- data/simplecov-1.0.0/lib/simplecov/configuration/formatting.rb +119 -0
- data/simplecov-1.0.0/lib/simplecov/configuration/ignored_entries.rb +63 -0
- data/simplecov-1.0.0/lib/simplecov/configuration/merging.rb +164 -0
- data/simplecov-1.0.0/lib/simplecov/configuration/thresholds.rb +174 -0
- data/simplecov-1.0.0/lib/simplecov/configuration.rb +184 -0
- data/simplecov-1.0.0/lib/simplecov/coverage_statistics.rb +59 -0
- data/simplecov-1.0.0/lib/simplecov/coverage_violations.rb +148 -0
- data/simplecov-1.0.0/lib/simplecov/defaults.rb +60 -0
- data/simplecov-1.0.0/lib/simplecov/deprecation.rb +45 -0
- data/simplecov-1.0.0/lib/simplecov/directive.rb +162 -0
- data/simplecov-1.0.0/lib/simplecov/exit_codes/exit_code_handling.rb +35 -0
- data/simplecov-1.0.0/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +45 -0
- data/simplecov-1.0.0/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +45 -0
- data/simplecov-1.0.0/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +44 -0
- data/simplecov-1.0.0/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +41 -0
- data/simplecov-1.0.0/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +70 -0
- data/simplecov-1.0.0/lib/simplecov/exit_codes.rb +18 -0
- data/simplecov-1.0.0/lib/simplecov/exit_handling.rb +158 -0
- data/simplecov-1.0.0/lib/simplecov/file_list.rb +164 -0
- data/simplecov-1.0.0/lib/simplecov/filter.rb +139 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/base.rb +101 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/application.css +1 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/application.js +18 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/favicon_green.png +0 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/favicon_red.png +0 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/favicon_yellow.png +0 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter/public/index.html +56 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/html_formatter.rb +79 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/json_formatter/errors_formatter.rb +84 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +128 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +99 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/json_formatter.rb +87 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/multi_formatter.rb +31 -0
- data/simplecov-1.0.0/lib/simplecov/formatter/simple_formatter.rb +23 -0
- data/simplecov-1.0.0/lib/simplecov/formatter.rb +14 -0
- data/simplecov-1.0.0/lib/simplecov/last_run.rb +35 -0
- data/simplecov-1.0.0/lib/simplecov/lines_classifier.rb +60 -0
- data/simplecov-1.0.0/lib/simplecov/load_global_config.rb +13 -0
- data/simplecov-1.0.0/lib/simplecov/no_defaults.rb +4 -0
- data/simplecov-1.0.0/lib/simplecov/parallel_adapters/base.rb +61 -0
- data/simplecov-1.0.0/lib/simplecov/parallel_adapters/generic.rb +44 -0
- data/simplecov-1.0.0/lib/simplecov/parallel_adapters/parallel_tests.rb +93 -0
- data/simplecov-1.0.0/lib/simplecov/parallel_adapters.rb +83 -0
- data/simplecov-1.0.0/lib/simplecov/parallel_coordination.rb +129 -0
- data/simplecov-1.0.0/lib/simplecov/process.rb +37 -0
- data/simplecov-1.0.0/lib/simplecov/profiles/bundler_filter.rb +5 -0
- data/simplecov-1.0.0/lib/simplecov/profiles/hidden_filter.rb +5 -0
- data/simplecov-1.0.0/lib/simplecov/profiles/rails.rb +32 -0
- data/simplecov-1.0.0/lib/simplecov/profiles/root_filter.rb +11 -0
- data/simplecov-1.0.0/lib/simplecov/profiles/strict.rb +32 -0
- data/simplecov-1.0.0/lib/simplecov/profiles/test_frameworks.rb +5 -0
- data/simplecov-1.0.0/lib/simplecov/profiles.rb +64 -0
- data/simplecov-1.0.0/lib/simplecov/result/missing_source_files_reporter.rb +49 -0
- data/simplecov-1.0.0/lib/simplecov/result/source_file_builder.rb +51 -0
- data/simplecov-1.0.0/lib/simplecov/result.rb +183 -0
- data/simplecov-1.0.0/lib/simplecov/result_adapter.rb +92 -0
- data/simplecov-1.0.0/lib/simplecov/result_merger/legacy_format_adapter.rb +28 -0
- data/simplecov-1.0.0/lib/simplecov/result_merger/resultset_file.rb +38 -0
- data/simplecov-1.0.0/lib/simplecov/result_merger/resultset_store.rb +50 -0
- data/simplecov-1.0.0/lib/simplecov/result_merger.rb +162 -0
- data/simplecov-1.0.0/lib/simplecov/result_processing.rb +179 -0
- data/simplecov-1.0.0/lib/simplecov/simulate_coverage.rb +75 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/branch.rb +82 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/branch_builder.rb +114 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/builder_context.rb +28 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/line.rb +77 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/line_builder.rb +43 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/method.rb +52 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/method_builder.rb +58 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/ruby_data_parser.rb +88 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/skip_chunks.rb +75 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/source_loader.rb +63 -0
- data/simplecov-1.0.0/lib/simplecov/source_file/statistics.rb +57 -0
- data/simplecov-1.0.0/lib/simplecov/source_file.rb +189 -0
- data/simplecov-1.0.0/lib/simplecov/static_coverage_extractor/method_collector.rb +55 -0
- data/simplecov-1.0.0/lib/simplecov/static_coverage_extractor/visitor.rb +171 -0
- data/simplecov-1.0.0/lib/simplecov/static_coverage_extractor.rb +110 -0
- data/simplecov-1.0.0/lib/simplecov/useless_results_remover.rb +27 -0
- data/simplecov-1.0.0/lib/simplecov/version.rb +5 -0
- data/simplecov-1.0.0/lib/simplecov-html.rb +4 -0
- data/simplecov-1.0.0/lib/simplecov.rb +255 -0
- data/simplecov-1.0.0/lib/simplecov_json_formatter.rb +4 -0
- data/simplecov-1.0.0/schemas/coverage-v1.0.schema.json +306 -0
- data/simplecov-1.0.0/schemas/coverage.schema.json +306 -0
- data/ultra-pro-pkg.gemspec +12 -0
- metadata +156 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "color"
|
|
4
|
+
require_relative "cli/dotfile"
|
|
5
|
+
require_relative "cli/clean"
|
|
6
|
+
require_relative "cli/coverage"
|
|
7
|
+
require_relative "cli/diff"
|
|
8
|
+
require_relative "cli/merge"
|
|
9
|
+
require_relative "cli/open"
|
|
10
|
+
require_relative "cli/report"
|
|
11
|
+
require_relative "cli/run"
|
|
12
|
+
require_relative "cli/serve"
|
|
13
|
+
require_relative "cli/uncovered"
|
|
14
|
+
|
|
15
|
+
module SimpleCov
|
|
16
|
+
# Lightweight command-line front-end. `run` dispatches a subcommand
|
|
17
|
+
# (`coverage`, `report`, `uncovered`, `merge`, `diff`, `open`, etc.) —
|
|
18
|
+
# see the `usage` text below for the full list, or run `simplecov help`.
|
|
19
|
+
#
|
|
20
|
+
# Read-only subcommands consume JSONFormatter output (`coverage.json`),
|
|
21
|
+
# which the bundled HTMLFormatter already drops alongside the HTML, so
|
|
22
|
+
# no runtime hooking is needed for those. Default paths follow the
|
|
23
|
+
# project's `.simplecov` `SimpleCov.coverage_dir` setting when one is
|
|
24
|
+
# present, so a project that writes its report somewhere other than
|
|
25
|
+
# `coverage/` doesn't have to pass `--input` / `--report` every
|
|
26
|
+
# invocation.
|
|
27
|
+
module CLI
|
|
28
|
+
COMMANDS = {
|
|
29
|
+
"coverage" => Coverage,
|
|
30
|
+
"run" => Run,
|
|
31
|
+
"open" => Open,
|
|
32
|
+
"report" => Report,
|
|
33
|
+
"uncovered" => Uncovered,
|
|
34
|
+
"merge" => Merge,
|
|
35
|
+
"diff" => Diff,
|
|
36
|
+
"serve" => Serve,
|
|
37
|
+
"clean" => Clean
|
|
38
|
+
}.freeze
|
|
39
|
+
|
|
40
|
+
module_function
|
|
41
|
+
|
|
42
|
+
# Resolved once per process. Walks up from cwd looking for a
|
|
43
|
+
# `.simplecov`; if present, the file is loaded with
|
|
44
|
+
# `SimpleCov.start` neutered so it can't trigger coverage tracking
|
|
45
|
+
# or an at_exit hook just because we asked it for a config value.
|
|
46
|
+
def coverage_dir
|
|
47
|
+
@coverage_dir ||= Dotfile.coverage_dir
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def default_input
|
|
51
|
+
File.join(coverage_dir, "coverage.json")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Resolve "should this subcommand colorize?" once per invocation.
|
|
55
|
+
# `--no-color` (opts[:no_color]) is the per-invocation kill-switch;
|
|
56
|
+
# otherwise we defer to `SimpleCov::Color.enabled?`, which honors
|
|
57
|
+
# `NO_COLOR` / `FORCE_COLOR` and falls back to `stream.tty?`.
|
|
58
|
+
def color_enabled?(opts, stream)
|
|
59
|
+
return false if opts[:no_color]
|
|
60
|
+
|
|
61
|
+
SimpleCov::Color.enabled?(stream)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def default_report
|
|
65
|
+
File.join(coverage_dir, "index.html")
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def default_resultset
|
|
69
|
+
File.join(coverage_dir, ".resultset.json")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Returns a process exit status (0 on success, non-zero on error).
|
|
73
|
+
def run(argv, stdout: $stdout, stderr: $stderr)
|
|
74
|
+
command, *rest = argv
|
|
75
|
+
handler = COMMANDS[command]
|
|
76
|
+
return handler.run(rest, stdout: stdout, stderr: stderr) if handler
|
|
77
|
+
return stdout.puts(usage) || 0 if [nil, "help", "--help", "-h"].include?(command)
|
|
78
|
+
|
|
79
|
+
stderr.puts("simplecov: unknown command #{command.inspect}", usage)
|
|
80
|
+
1
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def usage
|
|
84
|
+
<<~USAGE
|
|
85
|
+
Usage: simplecov <command> [options]
|
|
86
|
+
|
|
87
|
+
Commands:
|
|
88
|
+
run <command...> Execute <command> with simplecov pre-loaded
|
|
89
|
+
(so a coverage report is generated even
|
|
90
|
+
when the project has no test_helper hook)
|
|
91
|
+
coverage <path> Print coverage stats for the given file
|
|
92
|
+
report Print the overall summary and group totals
|
|
93
|
+
uncovered List the lowest-coverage files
|
|
94
|
+
merge <files...> Merge multiple .resultset.json files
|
|
95
|
+
diff <baseline> Show per-file coverage delta vs baseline
|
|
96
|
+
open Open the HTML report in the default browser
|
|
97
|
+
serve Serve the coverage report over HTTP
|
|
98
|
+
clean Remove the coverage report directory
|
|
99
|
+
help Show this message
|
|
100
|
+
|
|
101
|
+
Default paths follow SimpleCov.coverage_dir from a project's
|
|
102
|
+
`.simplecov` when one is present (#{coverage_dir} for this run).
|
|
103
|
+
|
|
104
|
+
coverage / report / uncovered / diff options:
|
|
105
|
+
--input PATH Read from PATH instead of #{default_input}
|
|
106
|
+
--no-color Disable colorized percentages
|
|
107
|
+
(also honors NO_COLOR / FORCE_COLOR env)
|
|
108
|
+
|
|
109
|
+
coverage options:
|
|
110
|
+
--json Print the file's JSON entry verbatim
|
|
111
|
+
|
|
112
|
+
report options:
|
|
113
|
+
--json Emit totals and group sections as JSON
|
|
114
|
+
|
|
115
|
+
uncovered options:
|
|
116
|
+
--threshold N Only show files below N% coverage
|
|
117
|
+
--top N Show at most N files (default: 10)
|
|
118
|
+
--criterion C line, branch, or method (default: line)
|
|
119
|
+
--json Emit results as a JSON array (for CI)
|
|
120
|
+
|
|
121
|
+
merge options:
|
|
122
|
+
--output PATH Write merged resultset to PATH
|
|
123
|
+
(default: #{default_resultset})
|
|
124
|
+
--honor-timeout Drop entries older than merge_timeout
|
|
125
|
+
--dry-run Print what would be written without
|
|
126
|
+
actually writing
|
|
127
|
+
-q, --quiet Suppress the success status line
|
|
128
|
+
|
|
129
|
+
diff options:
|
|
130
|
+
--fail-on-drop Exit non-zero when any file's coverage
|
|
131
|
+
dropped vs the baseline
|
|
132
|
+
--json Emit results as a JSON array (for CI)
|
|
133
|
+
--threshold N Only show files whose absolute delta
|
|
134
|
+
in any criterion is at least N%
|
|
135
|
+
|
|
136
|
+
open options:
|
|
137
|
+
--report PATH Open PATH instead of #{default_report}
|
|
138
|
+
|
|
139
|
+
serve options:
|
|
140
|
+
--port N Bind to port N (default: random open port)
|
|
141
|
+
--host HOST Bind to HOST (default: 127.0.0.1)
|
|
142
|
+
|
|
143
|
+
clean options:
|
|
144
|
+
--dry-run Print what would be removed without
|
|
145
|
+
deleting anything
|
|
146
|
+
-q, --quiet Suppress status lines
|
|
147
|
+
USAGE
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
# ANSI colorization for stderr diagnostics. Thresholds mirror the
|
|
5
|
+
# HTML formatter (>= 90 green, >= 75 yellow, otherwise red) so a
|
|
6
|
+
# team's mental model of "what's the cutoff" is the same whether
|
|
7
|
+
# they're reading the terminal output or the HTML report.
|
|
8
|
+
#
|
|
9
|
+
# Color precedence, highest first:
|
|
10
|
+
#
|
|
11
|
+
# - `SimpleCov.color = true` / `false` (programmatic override, wins
|
|
12
|
+
# over everything; default is `:auto` which falls through)
|
|
13
|
+
# - `NO_COLOR` env var (any non-empty value) → off (see no-color.org)
|
|
14
|
+
# - `FORCE_COLOR` env var (any non-empty value) → on
|
|
15
|
+
# - `stream.tty?` fallback
|
|
16
|
+
#
|
|
17
|
+
# `NO_COLOR` wins over `FORCE_COLOR` if both env vars are set.
|
|
18
|
+
module Color
|
|
19
|
+
GREEN_THRESHOLD = 90
|
|
20
|
+
YELLOW_THRESHOLD = 75
|
|
21
|
+
|
|
22
|
+
ANSI = {
|
|
23
|
+
red: "\e[31m",
|
|
24
|
+
yellow: "\e[33m",
|
|
25
|
+
green: "\e[32m",
|
|
26
|
+
reset: "\e[0m"
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
module_function
|
|
30
|
+
|
|
31
|
+
# `stream` is the IO that the colorized text is destined for. The
|
|
32
|
+
# formatter writes to stderr, so that's the default. CLI subcommands
|
|
33
|
+
# that print to stdout should pass `$stdout` so a redirected pipe
|
|
34
|
+
# doesn't get ANSI sequences. See the module-level comment for
|
|
35
|
+
# precedence.
|
|
36
|
+
def enabled?(stream = $stderr)
|
|
37
|
+
config = SimpleCov.color
|
|
38
|
+
return config if [true, false].include?(config)
|
|
39
|
+
return false if env_set?("NO_COLOR")
|
|
40
|
+
return true if env_set?("FORCE_COLOR")
|
|
41
|
+
|
|
42
|
+
stream.tty?
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def for_percent(percent)
|
|
46
|
+
return :green if percent >= GREEN_THRESHOLD
|
|
47
|
+
return :yellow if percent >= YELLOW_THRESHOLD
|
|
48
|
+
|
|
49
|
+
:red
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Wrap `text` in the ANSI sequence for `color` (a key of ANSI).
|
|
53
|
+
# Returns the bare text if color is disabled. The `enabled:`
|
|
54
|
+
# keyword lets callers (e.g., CLI subcommands honoring `--no-color`)
|
|
55
|
+
# override the auto-detection without touching env vars.
|
|
56
|
+
def colorize(text, color, enabled: enabled?)
|
|
57
|
+
return text unless enabled
|
|
58
|
+
|
|
59
|
+
"#{ANSI.fetch(color)}#{text}#{ANSI.fetch(:reset)}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Render `percent` as a fixed "NN.NN%" string colored by which
|
|
63
|
+
# threshold band it falls into. Callers that want a different
|
|
64
|
+
# rendering of the number can pass the pre-rendered `text`.
|
|
65
|
+
def colorize_percent(percent, text = nil, enabled: enabled?)
|
|
66
|
+
colorize(text || format("%.2f%%", percent), for_percent(percent), enabled: enabled)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def env_set?(name)
|
|
70
|
+
value = ENV.fetch(name, nil)
|
|
71
|
+
value && !value.empty?
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../source_file/ruby_data_parser"
|
|
4
|
+
|
|
5
|
+
module SimpleCov
|
|
6
|
+
module Combine
|
|
7
|
+
#
|
|
8
|
+
# Combine different branch coverage results on single file.
|
|
9
|
+
#
|
|
10
|
+
# Should be called through `SimpleCov.combine`.
|
|
11
|
+
module BranchesCombiner
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
#
|
|
15
|
+
# Return merged branches or the existed branch if other is missing.
|
|
16
|
+
#
|
|
17
|
+
# Branches inside files are always same if they exist, the difference only in coverage count.
|
|
18
|
+
# Branch coverage report for any conditional case is built from hash, it's key is a condition and
|
|
19
|
+
# it's body is a hash << keys from condition and value is coverage rate >>.
|
|
20
|
+
# ex: branches => { [:if, 3, 8, 6, 8, 36] =>
|
|
21
|
+
# {[:then, 4, 8, 6, 8, 12] => 1, [:else, 5, 8, 6, 8, 36] => 2}, ... }
|
|
22
|
+
# We create copy of result and update it values depending on the combined branches coverage values.
|
|
23
|
+
#
|
|
24
|
+
# @return [Hash]
|
|
25
|
+
#
|
|
26
|
+
def combine(coverage_a, coverage_b)
|
|
27
|
+
combined = [coverage_a, coverage_b].each_with_object({}) do |coverage, memo|
|
|
28
|
+
coverage.each do |condition, branches_inside|
|
|
29
|
+
condition_key = tuple_identity(condition)
|
|
30
|
+
condition_tuple, merged_branches = memo[condition_key] ||= [condition, {}]
|
|
31
|
+
merge_branches(merged_branches, branches_inside)
|
|
32
|
+
memo[condition_key] = [condition_tuple, merged_branches]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
combined.values.to_h { |condition, branches| [condition, branches.values.to_h] }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def merge_branches(target, source)
|
|
40
|
+
source.each do |branch, count|
|
|
41
|
+
branch_key = tuple_identity(branch)
|
|
42
|
+
branch_tuple, existing_count = target[branch_key]
|
|
43
|
+
target[branch_key] = [branch_tuple || branch, existing_count ? existing_count + count : count]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def tuple_identity(tuple)
|
|
48
|
+
tuple = SourceFile::RubyDataParser.call(tuple)
|
|
49
|
+
type, _id, start_line, start_column, end_line, end_column = tuple
|
|
50
|
+
[type, start_line, start_column, end_line, end_column]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
module Combine
|
|
5
|
+
#
|
|
6
|
+
# Handle combining two coverage results for same file
|
|
7
|
+
#
|
|
8
|
+
# Should be called through `SimpleCov.combine`.
|
|
9
|
+
module FilesCombiner
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
#
|
|
13
|
+
# Combines the results for 2 coverages of a file.
|
|
14
|
+
#
|
|
15
|
+
# @return [Hash]
|
|
16
|
+
#
|
|
17
|
+
def combine(coverage_a, coverage_b)
|
|
18
|
+
combination = {"lines" => Combine.combine(LinesCombiner, coverage_a["lines"], coverage_b["lines"])}
|
|
19
|
+
if SimpleCov.branch_coverage?
|
|
20
|
+
combined_branches = Combine.combine(BranchesCombiner, coverage_a["branches"], coverage_b["branches"])
|
|
21
|
+
combination["branches"] = combined_branches || {}
|
|
22
|
+
end
|
|
23
|
+
if SimpleCov.method_coverage?
|
|
24
|
+
combination["methods"] = Combine.combine(MethodsCombiner, coverage_a["methods"], coverage_b["methods"])
|
|
25
|
+
end
|
|
26
|
+
combination
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
module Combine
|
|
5
|
+
#
|
|
6
|
+
# Combine two different lines coverage results on same file
|
|
7
|
+
#
|
|
8
|
+
# Should be called through `SimpleCov.combine`.
|
|
9
|
+
module LinesCombiner
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
# Build a fresh array sized to the longer input. The previous
|
|
13
|
+
# implementation mutated whichever input was longer in place,
|
|
14
|
+
# which could surprise callers holding a reference to that array
|
|
15
|
+
# (e.g. the parsed `coverage` key of a resultset hash being
|
|
16
|
+
# passed into a second merge).
|
|
17
|
+
def combine(coverage_a, coverage_b)
|
|
18
|
+
size = [coverage_a.size, coverage_b.size].max
|
|
19
|
+
Array.new(size) { |i| merge_line_coverage(coverage_a[i], coverage_b[i]) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Two runs of the same source file should agree on which lines
|
|
23
|
+
# are coverage-relevant (`nil` for comments / whitespace, `0`+
|
|
24
|
+
# for executable). When they don't, treat "relevant on either
|
|
25
|
+
# side" as relevant rather than masking a real `0` as `nil`,
|
|
26
|
+
# which would silently drop an uncovered line from the
|
|
27
|
+
# denominator and inflate the percentage.
|
|
28
|
+
#
|
|
29
|
+
# Logic:
|
|
30
|
+
#
|
|
31
|
+
# => nil + nil = nil
|
|
32
|
+
# => nil + int = int (preserves a relevant-but-uncovered 0)
|
|
33
|
+
# => int + int = int (sum)
|
|
34
|
+
#
|
|
35
|
+
# @param [Integer || nil] first_val
|
|
36
|
+
# @param [Integer || nil] second_val
|
|
37
|
+
# @return [Integer || nil]
|
|
38
|
+
def merge_line_coverage(first_val, second_val)
|
|
39
|
+
return nil if first_val.nil? && second_val.nil?
|
|
40
|
+
|
|
41
|
+
first_val.to_i + second_val.to_i
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
module Combine
|
|
5
|
+
#
|
|
6
|
+
# Combine different method coverage results on a single file.
|
|
7
|
+
#
|
|
8
|
+
# Should be called through `SimpleCov.combine`.
|
|
9
|
+
module MethodsCombiner
|
|
10
|
+
module_function
|
|
11
|
+
|
|
12
|
+
#
|
|
13
|
+
# Return merged methods or the existing methods if other is missing.
|
|
14
|
+
#
|
|
15
|
+
# Method coverage is a flat hash mapping method identifiers to hit counts.
|
|
16
|
+
# Combining sums the hit counts for matching methods and preserves methods
|
|
17
|
+
# that only appear in one result.
|
|
18
|
+
#
|
|
19
|
+
# @return [Hash]
|
|
20
|
+
#
|
|
21
|
+
def combine(coverage_a, coverage_b)
|
|
22
|
+
coverage_a.merge(coverage_b) { |_key, a_count, b_count| a_count + b_count }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
module Combine
|
|
5
|
+
# There might be reports from different kinds of tests,
|
|
6
|
+
# e.g. RSpec and Cucumber. We need to combine their results
|
|
7
|
+
# into unified one. This class does that.
|
|
8
|
+
# To unite the results on file basis, it leverages
|
|
9
|
+
# the combine of lines and branches inside each file within given results.
|
|
10
|
+
module ResultsCombiner
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
#
|
|
14
|
+
# Combine process explanation
|
|
15
|
+
# => ResultCombiner: define all present files between results and start combine on file level.
|
|
16
|
+
# ==> FileCombiner: collect result of next combine levels lines, branches, and methods.
|
|
17
|
+
# ===> LinesCombiner: combine lines results.
|
|
18
|
+
# ===> BranchesCombiner: combine branches results.
|
|
19
|
+
# ===> MethodsCombiner: combine methods results.
|
|
20
|
+
#
|
|
21
|
+
# @return [Hash]
|
|
22
|
+
#
|
|
23
|
+
def combine(*results)
|
|
24
|
+
results.reduce({}) do |combined_results, next_result|
|
|
25
|
+
combine_result_sets(combined_results, next_result)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
#
|
|
30
|
+
# Manage combining results on files level
|
|
31
|
+
#
|
|
32
|
+
# @param [Hash] combined_results
|
|
33
|
+
# @param [Hash] result
|
|
34
|
+
#
|
|
35
|
+
# @return [Hash]
|
|
36
|
+
#
|
|
37
|
+
def combine_result_sets(combined_results, result)
|
|
38
|
+
results_files = combined_results.keys | result.keys
|
|
39
|
+
|
|
40
|
+
results_files.to_h do |file_name|
|
|
41
|
+
[file_name, combine_file_coverage(
|
|
42
|
+
combined_results[file_name],
|
|
43
|
+
result[file_name]
|
|
44
|
+
)]
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# Combine two files coverage results
|
|
50
|
+
#
|
|
51
|
+
# @param [Hash] coverage_a
|
|
52
|
+
# @param [Hash] coverage_b
|
|
53
|
+
#
|
|
54
|
+
# @return [Hash]
|
|
55
|
+
#
|
|
56
|
+
def combine_file_coverage(coverage_a, coverage_b)
|
|
57
|
+
Combine.combine(Combine::FilesCombiner, coverage_a, coverage_b)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
# Functionally for combining coverage results
|
|
5
|
+
#
|
|
6
|
+
module Combine
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
#
|
|
10
|
+
# Combine two coverage based on the given combiner_module.
|
|
11
|
+
#
|
|
12
|
+
# Combiners should always be called through this interface,
|
|
13
|
+
# as it takes care of short-circuiting of one of the coverages is nil.
|
|
14
|
+
#
|
|
15
|
+
# @return [Hash]
|
|
16
|
+
def combine(combiner_module, coverage_a, coverage_b)
|
|
17
|
+
return existing_coverage(coverage_a, coverage_b) if empty_coverage?(coverage_a, coverage_b)
|
|
18
|
+
|
|
19
|
+
combiner_module.combine(coverage_a, coverage_b)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def empty_coverage?(coverage_a, coverage_b)
|
|
23
|
+
!(coverage_a && coverage_b)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def existing_coverage(coverage_a, coverage_b)
|
|
27
|
+
coverage_a || coverage_b
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SimpleCov
|
|
4
|
+
#
|
|
5
|
+
# Helper that tries to find out what test suite is running (for SimpleCov.command_name)
|
|
6
|
+
#
|
|
7
|
+
module CommandGuesser
|
|
8
|
+
class << self
|
|
9
|
+
# Storage for the original command line call that invoked the test suite.
|
|
10
|
+
# This has got to be stored as early as possible because i.e. rake and test/unit 2
|
|
11
|
+
# have a habit of tampering with ARGV, which makes i.e. the automatic distinction
|
|
12
|
+
# between rails unit/functional/integration tests impossible without this cached
|
|
13
|
+
# item.
|
|
14
|
+
attr_accessor :original_run_command
|
|
15
|
+
|
|
16
|
+
def guess
|
|
17
|
+
[from_command_line_options || from_defined_constants, parallel_data].compact.join(" ")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
# When parallel_tests (or a compatible runner) is driving the suite,
|
|
23
|
+
# tag the command name with this worker's position in the pool.
|
|
24
|
+
def parallel_data
|
|
25
|
+
groups, number = ENV.values_at("PARALLEL_TEST_GROUPS", "TEST_ENV_NUMBER")
|
|
26
|
+
return unless groups && number
|
|
27
|
+
|
|
28
|
+
# parallel_tests sets the first worker's TEST_ENV_NUMBER to "" rather
|
|
29
|
+
# than "1"; restore the position so the rendered label reads cleanly.
|
|
30
|
+
number = "1" if number.empty?
|
|
31
|
+
"(#{number}/#{groups})"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
COMMAND_LINE_FRAMEWORKS = {
|
|
35
|
+
%r{test/functional/} => "Functional Tests",
|
|
36
|
+
%r{test/\{.*functional.*\}/} => "Functional Tests",
|
|
37
|
+
%r{test/integration/} => "Integration Tests",
|
|
38
|
+
%r{test/} => "Unit Tests",
|
|
39
|
+
/spec/ => "RSpec",
|
|
40
|
+
/cucumber/ => "Cucumber Features",
|
|
41
|
+
/features/ => "Cucumber Features"
|
|
42
|
+
}.freeze
|
|
43
|
+
private_constant :COMMAND_LINE_FRAMEWORKS
|
|
44
|
+
|
|
45
|
+
def from_command_line_options
|
|
46
|
+
COMMAND_LINE_FRAMEWORKS.find { |pattern, _| pattern.match?(original_run_command.to_s) }&.last
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Inner array literals after the first are flagged uncovered by Ruby's
|
|
50
|
+
# Coverage module even though the constant evaluates as a whole — known
|
|
51
|
+
# quirk with multi-line array literals.
|
|
52
|
+
DEFINED_CONSTANT_FRAMEWORKS = [
|
|
53
|
+
["RSpec", -> { defined?(::RSpec) }],
|
|
54
|
+
["Unit Tests", -> { defined?(Test::Unit) }], # simplecov:disable
|
|
55
|
+
["Minitest", -> { defined?(::Minitest) }], # simplecov:disable
|
|
56
|
+
["MiniTest", -> { defined?(MiniTest) }] # simplecov:disable
|
|
57
|
+
].freeze
|
|
58
|
+
private_constant :DEFINED_CONSTANT_FRAMEWORKS
|
|
59
|
+
|
|
60
|
+
# If the command regexps fail, let's try checking defined constants.
|
|
61
|
+
def from_defined_constants
|
|
62
|
+
# simplecov:disable branch — first iter returns when ::RSpec is defined; later branches unreachable
|
|
63
|
+
DEFINED_CONSTANT_FRAMEWORKS.each { |name, defined_check| return name if defined_check.call }
|
|
64
|
+
# simplecov:enable branch
|
|
65
|
+
|
|
66
|
+
# TODO: Provide link to docs/wiki article
|
|
67
|
+
# simplecov:disable — only fires when no framework is detected, which
|
|
68
|
+
# is impossible while our own specs are running under rspec
|
|
69
|
+
warn(
|
|
70
|
+
"SimpleCov failed to recognize the test framework and/or suite used. " \
|
|
71
|
+
"Please specify manually using SimpleCov.command_name 'Unit Tests'."
|
|
72
|
+
)
|
|
73
|
+
"Unknown Test Framework"
|
|
74
|
+
# simplecov:enable
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|