Module: Kettle::Soup::Cover
- Extended by:
- Loaders
- Includes:
- Constants
- Defined in:
- lib/kettle/soup/cover.rb,
lib/kettle/soup/cover/loaders.rb,
lib/kettle/soup/cover/version.rb,
lib/kettle/soup/cover/constants.rb,
lib/kettle/soup/cover/formatters.rb,
lib/kettle/soup/cover/filters/gt_line_filter.rb,
lib/kettle/soup/cover/filters/lt_line_filter.rb,
sig/kettle/soup/cover.rbs
Defined Under Namespace
Modules: Constants, Filters, Loaders, Version
Classes: Error
Constant Summary
collapse
- VAR_HOME_PREFIX =
%r{\A/var/home(?=/|\z)}
- VERSION =
Current gem version exposed at the traditional constant location.
Version::VERSION
- CI =
- COMMAND_NAME =
- COVERAGE_DIR =
- DEBUG =
- DO_COV =
- ENV_GET =
- FALSE =
- FILTER_DIRS =
- FORMATTERS =
- FORMATTER_PLUGINS =
- IS_CI =
- MERGE_TIMEOUT =
- MIN_COVERAGE_BRANCH =
- MIN_COVERAGE_HARD =
- MIN_COVERAGE_LINE =
- MULTI_FORMATTERS =
- MULTI_FORMATTERS_DEFAULT =
- PREFIX =
- TRUE =
- OPEN_BIN =
- USE_MERGING =
- VERBOSE =
- WASHED_CONSTANTS =
Constants included
from Constants
Constants::CLEAN_RESULTSET, Constants::CLEAN_RESULTSET_DEFAULT, Constants::COVERAGE_ROOT_DIR, Constants::MIN_COVERAGE_HARD_REQUESTED, Constants::QUIET_COLLATION, Constants::SIMPLECOV_COMMAND_NAME, Constants::TEST_ENV_NUMBER, Constants::TURBO_TESTS, Constants::TURBO_TESTS_DIR, Constants::TURBO_TESTS_WORKER
Class Method Summary
collapse
-
.clean_resultset! ⇒ Object
Deletes coverage/.resultset.json (if it exists) so that stale entries from prior runs cannot pollute the current run's coverage report.
-
.clear_coverage_dir!(coverage_dir = Constants::COVERAGE_DIR, project_root: Dir.pwd) ⇒ Object
-
.clear_turbo_tests_coverage_dir!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
-
.collate_turbo_tests_coverage!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
-
.configure_formatters! ⇒ Object
-
.coverage_task_env(coverage_dir = Constants::COVERAGE_DIR, project_root: Dir.pwd) ⇒ Object
-
.display_path(path) ⇒ Object
-
.mark_turbo_tests_collated!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
-
.merge_branch_coverage(left, right) ⇒ Object
-
.merge_branch_entry(left, right) ⇒ Object
-
.merge_coverage_value(left, right) ⇒ Object
-
.merge_json_coverage!(target, source) ⇒ Object
-
.merge_line_coverage(left, right) ⇒ Object
-
.publish_turbo_tests_json_coverage!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
-
.quiet_collation_formatter_line?(line) ⇒ Boolean
-
.refresh_coverage_data!(coverage_dir = Constants::COVERAGE_DIR, project_root: Dir.pwd, out: $stdout, err: $stderr) ⇒ Object
-
.replay_quiet_collation_output(output, io) ⇒ Object
-
.turbo_tests_collated?(resultsets, coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Boolean
-
.turbo_tests_collation_marker_path(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
-
.turbo_tests_coverage? ⇒ Boolean
-
.turbo_tests_coverage_dir(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
-
.turbo_tests_json_paths(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
-
.turbo_tests_resultset_paths(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
-
.with_quiet_collation_output ⇒ Object
Instance Method Summary
collapse
Class Method Details
.clean_resultset! ⇒ Object
Deletes coverage/.resultset.json (if it exists) so that stale entries
from prior runs cannot pollute the current run's coverage report.
Called automatically from config.rb when CLEAN_RESULTSET is true.
56
57
58
59
|
# File 'lib/kettle/soup/cover.rb', line 56
def clean_resultset!
resultset_path = SimpleCov::ResultMerger.resultset_path
File.delete(resultset_path) if File.exist?(resultset_path)
end
|
.clear_coverage_dir!(coverage_dir = Constants::COVERAGE_DIR, project_root: Dir.pwd) ⇒ Object
61
62
63
|
# File 'lib/kettle/soup/cover.rb', line 61
def clear_coverage_dir!(coverage_dir = Constants::COVERAGE_DIR, project_root: Dir.pwd)
FileUtils.rm_rf(File.expand_path(coverage_dir, project_root))
end
|
.clear_turbo_tests_coverage_dir!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
73
74
75
|
# File 'lib/kettle/soup/cover.rb', line 73
def clear_turbo_tests_coverage_dir!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd)
FileUtils.rm_rf(turbo_tests_coverage_dir(coverage_dir, project_root: project_root))
end
|
.collate_turbo_tests_coverage!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
# File 'lib/kettle/soup/cover.rb', line 89
def collate_turbo_tests_coverage!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd)
return :disabled unless turbo_tests_coverage?
resultsets = turbo_tests_resultset_paths(coverage_dir, project_root: project_root)
return :empty if resultsets.empty?
return :already_collated if turbo_tests_collated?(resultsets, coverage_dir, project_root: project_root)
require "simplecov"
with_quiet_collation_output do
SimpleCov.collate(resultsets) do
command_name("#{Constants::COMMAND_NAME} (turbo_tests2)")
enable_coverage(:branch)
primary_coverage(:branch)
skip(Constants::FILTER_DIRS)
coverage_dir(File.expand_path(coverage_dir, project_root))
Kettle::Soup::Cover.configure_formatters!
if Constants::MIN_COVERAGE_HARD
minimum_coverage(
branch: Constants::MIN_COVERAGE_BRANCH,
line: Constants::MIN_COVERAGE_LINE
)
end
end
end
SimpleCov.external_at_exit = true if SimpleCov.respond_to?(:external_at_exit=)
publish_turbo_tests_json_coverage!(coverage_dir, project_root: project_root)
mark_turbo_tests_collated!(coverage_dir, project_root: project_root)
:collated
end
|
.coverage_task_env(coverage_dir = Constants::COVERAGE_DIR, project_root: Dir.pwd) ⇒ Object
.display_path(path) ⇒ Object
47
48
49
50
51
|
# File 'lib/kettle/soup/cover.rb', line 47
def display_path(path)
return path if path.nil?
path.to_s.sub(VAR_HOME_PREFIX, "/home")
end
|
.mark_turbo_tests_collated!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
132
133
134
135
136
|
# File 'lib/kettle/soup/cover.rb', line 132
def mark_turbo_tests_collated!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd)
marker_path = turbo_tests_collation_marker_path(coverage_dir, project_root: project_root)
FileUtils.mkdir_p(File.dirname(marker_path))
FileUtils.touch(marker_path)
end
|
.merge_branch_coverage(left, right) ⇒ Object
172
173
174
175
|
# File 'lib/kettle/soup/cover.rb', line 172
def merge_branch_coverage(left, right)
length = [left.length, right.length].max
Array.new(length) { |index| merge_branch_entry(left[index], right[index]) }.compact
end
|
.merge_branch_entry(left, right) ⇒ Object
177
178
179
180
181
182
183
184
185
|
# File 'lib/kettle/soup/cover.rb', line 177
def merge_branch_entry(left, right)
return right unless left
return left unless right
return left unless left.is_a?(Hash) && right.is_a?(Hash)
left.merge(right) do |key, left_value, right_value|
(key == "coverage") ? merge_coverage_value(left_value, right_value) : left_value
end
end
|
.merge_coverage_value(left, right) ⇒ Object
187
188
189
190
191
192
193
194
|
# File 'lib/kettle/soup/cover.rb', line 187
def merge_coverage_value(left, right)
return left + right if left.is_a?(Integer) && right.is_a?(Integer)
return left if left.is_a?(Integer)
return right if right.is_a?(Integer)
return left if left
right
end
|
.merge_json_coverage!(target, source) ⇒ Object
158
159
160
161
162
163
164
165
|
# File 'lib/kettle/soup/cover.rb', line 158
def merge_json_coverage!(target, source)
source.each do |path, coverage|
target[path] ||= {"lines" => [], "branches" => []}
target[path]["lines"] = merge_line_coverage(target[path]["lines"], coverage["lines"] || [])
target[path]["branches"] = merge_branch_coverage(target[path]["branches"] || [], coverage["branches"] || [])
end
target
end
|
.merge_line_coverage(left, right) ⇒ Object
167
168
169
170
|
# File 'lib/kettle/soup/cover.rb', line 167
def merge_line_coverage(left, right)
length = [left.length, right.length].max
Array.new(length) { |index| merge_coverage_value(left[index], right[index]) }
end
|
.publish_turbo_tests_json_coverage!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
# File 'lib/kettle/soup/cover.rb', line 138
def publish_turbo_tests_json_coverage!(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd)
paths = turbo_tests_json_paths(coverage_dir, project_root: project_root)
return :empty if paths.empty?
merged = {
"meta" => {},
"coverage" => {}
}
paths.sort_by { |path| File.basename(File.dirname(path)).to_i }.each do |path|
data = JSON.parse(File.read(path))
merged["meta"].merge!(data["meta"]) if data["meta"].is_a?(Hash)
merge_json_coverage!(merged["coverage"], data["coverage"] || {})
end
output_path = File.expand_path(File.join(coverage_dir, "coverage.json"), project_root)
FileUtils.mkdir_p(File.dirname(output_path))
File.write(output_path, JSON.pretty_generate(merged))
:published
end
|
222
223
224
225
226
227
228
229
|
# File 'lib/kettle/soup/cover.rb', line 222
def quiet_collation_formatter_line?(line)
stripped = line.strip
return true if stripped.empty?
return true if stripped.match?(/coverage report generated/i)
return true if stripped.match?(/\A(?:Line|Branch) coverage:/i)
false
end
|
.refresh_coverage_data!(coverage_dir = Constants::COVERAGE_DIR, project_root: Dir.pwd, out: $stdout, err: $stderr) ⇒ Object
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
|
# File 'lib/kettle/soup/cover.rb', line 245
def refresh_coverage_data!(coverage_dir = Constants::COVERAGE_DIR, project_root: Dir.pwd, out: $stdout, err: $stderr)
clear_coverage_dir!(coverage_dir, project_root: project_root)
coverage_task = File.expand_path("bin/rake", project_root)
success = system(
coverage_task_env(coverage_dir, project_root: project_root),
coverage_task,
"coverage",
chdir: project_root,
out: out,
err: err
)
return if success
raise Error, "Coverage refresh failed: #{coverage_task} coverage"
end
|
.replay_quiet_collation_output(output, io) ⇒ Object
216
217
218
219
220
|
# File 'lib/kettle/soup/cover.rb', line 216
def replay_quiet_collation_output(output, io)
output.each_line do |line|
io.print(line) unless quiet_collation_formatter_line?(line)
end
end
|
.turbo_tests_collated?(resultsets, coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Boolean
124
125
126
127
128
129
130
|
# File 'lib/kettle/soup/cover.rb', line 124
def turbo_tests_collated?(resultsets, coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd)
marker_path = turbo_tests_collation_marker_path(coverage_dir, project_root: project_root)
return false unless File.file?(marker_path)
marker_mtime = File.mtime(marker_path)
resultsets.all? { |path| File.file?(path) && File.mtime(path) <= marker_mtime }
end
|
.turbo_tests_collation_marker_path(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
85
86
87
|
# File 'lib/kettle/soup/cover.rb', line 85
def turbo_tests_collation_marker_path(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd)
File.expand_path(File.join(coverage_dir, ".turbo_tests_collated"), project_root)
end
|
.turbo_tests_coverage? ⇒ Boolean
.turbo_tests_coverage_dir(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
.turbo_tests_json_paths(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
81
82
83
|
# File 'lib/kettle/soup/cover.rb', line 81
def turbo_tests_json_paths(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd)
Dir[File.join(turbo_tests_coverage_dir(coverage_dir, project_root: project_root), "*", "coverage.json")]
end
|
.turbo_tests_resultset_paths(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd) ⇒ Object
77
78
79
|
# File 'lib/kettle/soup/cover.rb', line 77
def turbo_tests_resultset_paths(coverage_dir = Constants::COVERAGE_ROOT_DIR, project_root: Dir.pwd)
Dir[File.join(turbo_tests_coverage_dir(coverage_dir, project_root: project_root), "*", ".resultset.json")]
end
|
.with_quiet_collation_output ⇒ Object
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
# File 'lib/kettle/soup/cover.rb', line 196
def with_quiet_collation_output
return yield unless Constants::QUIET_COLLATION && !Constants::VERBOSE
stdout = StringIO.new
stderr = StringIO.new
original_stdout = $stdout
original_stderr = $stderr
begin
$stdout = stdout
$stderr = stderr
yield
ensure
$stdout = original_stdout
$stderr = original_stderr
replay_quiet_collation_output(stdout.string, original_stdout)
replay_quiet_collation_output(stderr.string, original_stderr)
end
end
|
Instance Method Details
#install_tasks ⇒ void
This method returns an undefined value.
28
|
# File 'sig/kettle/soup/cover.rbs', line 28
def install_tasks: () -> void
|
#load_filters ⇒ void
This method returns an undefined value.
29
|
# File 'sig/kettle/soup/cover.rbs', line 29
def load_filters: () -> void
|
This method returns an undefined value.
30
|
# File 'sig/kettle/soup/cover.rbs', line 30
def load_formatters: () -> void
|