simplecov 0.18.0.beta1 → 0.18.0.beta2
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/CHANGELOG.md +16 -1
- data/README.md +100 -16
- data/lib/simplecov.rb +76 -17
- data/lib/simplecov/combine/files_combiner.rb +3 -4
- data/lib/simplecov/combine/results_combiner.rb +50 -10
- data/lib/simplecov/configuration.rb +21 -5
- data/lib/simplecov/defaults.rb +3 -1
- data/lib/simplecov/last_run.rb +1 -1
- data/lib/simplecov/result.rb +8 -18
- data/lib/simplecov/result_adapter.rb +1 -1
- data/lib/simplecov/result_merger.rb +7 -1
- data/lib/simplecov/simulate_coverage.rb +2 -2
- data/lib/simplecov/source_file.rb +16 -47
- data/lib/simplecov/source_file/branch.rb +4 -26
- data/lib/simplecov/useless_results_remover.rb +1 -1
- data/lib/simplecov/version.rb +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eeee06c5cbeaf6c89000a43641f7a6163d9b267d145698e742089385eae6e2b8
|
4
|
+
data.tar.gz: 76e7182adc3c8156e021d780618733f6237a81723656f0123b51abf34a63e891
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5e785e01ff4bf53c9cbdbeaeb7cc5925265e2ec9cacecb9865261150eed13b8c59c43d840588eb6baa0565ce510c74891f535f02bb1db42d2eeea4e61b3cd54
|
7
|
+
data.tar.gz: d8f29ed7d8ecf8a01d9fcd843a0c2a9845f022a690c8c7096c23077f7e3c2488fce290e099e70083ee44e37d1bb05f1535c2ec1a70b6952929ab92857b38a339
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
0.18.0.beta2 (unreleased)
|
2
|
+
===================
|
3
|
+
|
4
|
+
## Enhancements
|
5
|
+
* only turn on the requested coverage criteria (when activating branch coverage before SimpleCov would also instruct Ruby to take Method coverage)
|
6
|
+
* Change how branch coverage is displayed, now it's `branch_type: hit_count` which should be more self explanatory. See [#830](https://github.com/colszowka/simplecov/pull/830) for an example and feel free to give feedback!
|
7
|
+
* Allow early running exit tasks and avoid the `at_exit` hook through the `SimpleCov.run_exit_tasks!` method. (thanks [@macumber]: https://github.com/macumber))
|
8
|
+
* Allow manual collation of result sets through the `SimpleCov.collate` entrypoint. See the README for more details (thanks [@ticky](https://github.com/ticky))
|
9
|
+
* Within `case`, even if there is no `else` branch declared show missing coverage for it (aka no branch of it). See [#825](https://github.com/colszowka/simplecov/pull/825)
|
10
|
+
* Stop symbolizing all keys when loading cache (should lead to be faster and consume less memory)
|
11
|
+
* Cache whether we can use/are using branch coverage (should be slightly faster)
|
12
|
+
|
13
|
+
## Bugfixes
|
14
|
+
* Fix a crash that happened when an old version of our internal cache file `.resultset.json` was still present
|
15
|
+
|
1
16
|
0.18.0.beta1 (2020-01-05)
|
2
17
|
===================
|
3
18
|
|
@@ -8,7 +23,7 @@ This release is still beta because we'd love for you to test out branch coverage
|
|
8
23
|
On a personal note from [@PragTob](https://github.com/PragTob/) thanks to [ruby together](https://rubytogether.org/) for sponsoring this work on SimpleCov making it possible to deliver this and subsequent releases.
|
9
24
|
|
10
25
|
## Breaking
|
11
|
-
* Dropped
|
26
|
+
* Dropped support for all EOL'ed rubies meaning we only support 2.4+. Simplecov can no longer be installed on older rubies, but older simplecov releases should still work. (thanks [@deivid-rodriguez](https://github.com/deivid-rodriguez))
|
12
27
|
* Dropped the `rake simplecov` task that "magically" integreated with rails. It was always undocumented, caused some issues and [had some issues](https://github.com/colszowka/simplecov/issues/689#issuecomment-561572327). Use the integration as described in the README please :)
|
13
28
|
|
14
29
|
## Enhancements
|
data/README.md
CHANGED
@@ -170,6 +170,17 @@ to use SimpleCov with them. Here's an overview of the known ones:
|
|
170
170
|
<a href="https://github.com/colszowka/simplecov/pull/185">#185</a>
|
171
171
|
</td>
|
172
172
|
</tr>
|
173
|
+
<tr>
|
174
|
+
<th>
|
175
|
+
knapsack_pro
|
176
|
+
</th>
|
177
|
+
<td>
|
178
|
+
To make SimpleCov work with Knapsack Pro Queue Mode to split tests in parallel on CI jobs you need to provide CI node index number to the <code>SimpleCov.command_name</code> in <code>KnapsackPro::Hooks::Queue.before_queue</code> hook.
|
179
|
+
</td>
|
180
|
+
<td>
|
181
|
+
<a href="https://knapsackpro.com/faq/question/how-to-use-simplecov-in-queue-mode">Tip</a>
|
182
|
+
</td>
|
183
|
+
</tr>
|
173
184
|
<tr>
|
174
185
|
<th>
|
175
186
|
RubyMine
|
@@ -308,12 +319,16 @@ return if number.odd?
|
|
308
319
|
```
|
309
320
|
|
310
321
|
If all the code in that method was covered you'd never know if the guard clause was ever
|
311
|
-
triggered
|
322
|
+
triggered! With line coverage as just evaluating the condition marks it as covered.
|
323
|
+
|
324
|
+
In the HTML report the lines of code will be annotated like `branch_type: hit_count`:
|
312
325
|
|
313
|
-
|
326
|
+
* `then: 2` - the then branch (of an `if`) was executed twice
|
327
|
+
* `else: 0` - the else branch (of an `if` or `case`) was never executed
|
314
328
|
|
315
|
-
|
316
|
-
|
329
|
+
Not that even if you don't declare an `else` branch it will still show up in the coverage
|
330
|
+
reports meaning that the condition of the `if` was not hit or that no `when` of `case`
|
331
|
+
was hit during the test runs.
|
317
332
|
|
318
333
|
**Is branch coverage strictly better?** No. Branch coverage really only concerns itself with
|
319
334
|
conditionals - meaning coverage of sequential code is of no interest to it. A file without
|
@@ -461,12 +476,11 @@ end
|
|
461
476
|
|
462
477
|
You normally want to have your coverage analyzed across ALL of your test suites, right?
|
463
478
|
|
464
|
-
Simplecov automatically caches coverage results in your
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
There are two things to note here though:
|
479
|
+
Simplecov automatically caches coverage results in your
|
480
|
+
(coverage_path)/.resultset.json, and will merge or override those with
|
481
|
+
subsequent runs, depending on whether simplecov considers those subsequent runs
|
482
|
+
as different test suites or as the same test suite as the cached results. To
|
483
|
+
make this distinction, simplecov has the concept of "test suite names".
|
470
484
|
|
471
485
|
### Test suite names
|
472
486
|
|
@@ -520,14 +534,84 @@ SimpleCov.command_name "features" + (ENV['TEST_ENV_NUMBER'] || '')
|
|
520
534
|
|
521
535
|
[simplecov-html] prints the used test suites in the footer of the generated coverage report.
|
522
536
|
|
523
|
-
### Timeout for merge
|
524
537
|
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
538
|
+
### Merging test runs under the same execution environment
|
539
|
+
|
540
|
+
Test results are automatically merged with previous runs in the same execution
|
541
|
+
environment when generating the result, so when coverage is set up properly for
|
542
|
+
Cucumber and your unit / functional / integration tests, all of those test
|
543
|
+
suites will be taken into account when building the coverage report.
|
529
544
|
|
530
|
-
|
545
|
+
#### Timeout for merge
|
546
|
+
|
547
|
+
Of course, your cached coverage data is likely to become invalid at some point. Thus, when automatically merging
|
548
|
+
subsequent test runs, result sets that are older than `SimpleCov.merge_timeout` will not be used any more. By default,
|
549
|
+
the timeout is 600 seconds (10 minutes), and you can raise (or lower) it by specifying `SimpleCov.merge_timeout 3600`
|
550
|
+
(1 hour), or, inside a configure/start block, with just `merge_timeout 3600`.
|
551
|
+
|
552
|
+
You can deactivate this automatic merging altogether with `SimpleCov.use_merging false`.
|
553
|
+
|
554
|
+
### Merging test runs under different execution environments
|
555
|
+
|
556
|
+
If your tests are done in parallel across multiple build machines, you can fetch them all and merge them into a single
|
557
|
+
result set using the `SimpleCov.collate` method. This can be added to a Rakefile or script file, having downloaded a set of
|
558
|
+
`.resultset.json` files from each parallel test run.
|
559
|
+
|
560
|
+
```ruby
|
561
|
+
# lib/tasks/coverage_report.rake
|
562
|
+
namespace :coverage do
|
563
|
+
desc "Collates all result sets generated by the different test runners"
|
564
|
+
task :report do
|
565
|
+
require 'simplecov'
|
566
|
+
|
567
|
+
SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"]
|
568
|
+
end
|
569
|
+
end
|
570
|
+
```
|
571
|
+
|
572
|
+
`SimpleCov.collate` also takes an optional simplecov profile and an optional
|
573
|
+
block for configuration, just the same as `SimpleCov.start` or
|
574
|
+
`SimpleCov.configure`. This means you can configure a separate formatter for
|
575
|
+
the collated output. For instance, you can make the formatter in
|
576
|
+
`SimpleCov.start` the `SimpleCov::Formatter::SimpleFormatter`, and only use more
|
577
|
+
complex formatters in the final `SimpleCov.collate` run.
|
578
|
+
|
579
|
+
```ruby
|
580
|
+
# spec/spec_helper.rb
|
581
|
+
require 'simplecov'
|
582
|
+
|
583
|
+
SimpleCov.start 'rails' do
|
584
|
+
# Disambiguates individual test runs
|
585
|
+
command_name "Job #{ENV["TEST_ENV_NUMBER"]}" if ENV["TEST_ENV_NUMBER"]
|
586
|
+
|
587
|
+
if ENV['CI']
|
588
|
+
formatter SimpleCov::Formatter::SimpleFormatter
|
589
|
+
else
|
590
|
+
formatter SimpleCov::Formatter::MultiFormatter.new([
|
591
|
+
SimpleCov::Formatter::SimpleFormatter,
|
592
|
+
SimpleCov::Formatter::HTMLFormatter
|
593
|
+
])
|
594
|
+
end
|
595
|
+
|
596
|
+
track_files "**/*.rb"
|
597
|
+
end
|
598
|
+
```
|
599
|
+
|
600
|
+
```ruby
|
601
|
+
# lib/tasks/coverage_report.rake
|
602
|
+
namespace :coverage do
|
603
|
+
task :report do
|
604
|
+
require 'simplecov'
|
605
|
+
|
606
|
+
SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' do
|
607
|
+
formatter SimpleCov::Formatter::MultiFormatter.new([
|
608
|
+
SimpleCov::Formatter::SimpleFormatter,
|
609
|
+
SimpleCov::Formatter::HTMLFormatter
|
610
|
+
])
|
611
|
+
end
|
612
|
+
end
|
613
|
+
end
|
614
|
+
```
|
531
615
|
|
532
616
|
## Running coverage only on demand
|
533
617
|
|
data/lib/simplecov.rb
CHANGED
@@ -46,13 +46,48 @@ module SimpleCov
|
|
46
46
|
#
|
47
47
|
def start(profile = nil, &block)
|
48
48
|
require "coverage"
|
49
|
-
|
50
|
-
configure(&block) if block_given?
|
49
|
+
initial_setup(profile, &block)
|
51
50
|
@result = nil
|
52
|
-
self.running = true
|
53
51
|
self.pid = Process.pid
|
54
52
|
|
55
|
-
|
53
|
+
start_coverage_measurement
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# Collate a series of SimpleCov result files into a single SimpleCov output.
|
58
|
+
# You can optionally specify configuration with a block:
|
59
|
+
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"]
|
60
|
+
# OR
|
61
|
+
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' # using rails profile
|
62
|
+
# OR
|
63
|
+
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"] do
|
64
|
+
# add_filter 'test'
|
65
|
+
# end
|
66
|
+
# OR
|
67
|
+
# SimpleCov.collate Dir["simplecov-resultset-*/.resultset.json"], 'rails' do
|
68
|
+
# add_filter 'test'
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# Please check out the RDoc for SimpleCov::Configuration to find about
|
72
|
+
# available config options, or checkout the README for more in-depth
|
73
|
+
# information about coverage collation
|
74
|
+
#
|
75
|
+
def collate(result_filenames, profile = nil, &block)
|
76
|
+
raise "There's no reports to be merged" if result_filenames.empty?
|
77
|
+
|
78
|
+
initial_setup(profile, &block)
|
79
|
+
|
80
|
+
results = result_filenames.flat_map do |filename|
|
81
|
+
# Re-create each included instance of SimpleCov::Result from the stored run data.
|
82
|
+
(JSON.parse(File.read(filename)) || {}).map do |command_name, coverage|
|
83
|
+
SimpleCov::Result.from_hash(command_name => coverage)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Use the ResultMerger to produce a single, merged result, ready to use.
|
88
|
+
@result = SimpleCov::ResultMerger.merge_and_store(*results)
|
89
|
+
|
90
|
+
run_exit_tasks!
|
56
91
|
end
|
57
92
|
|
58
93
|
#
|
@@ -159,6 +194,8 @@ module SimpleCov
|
|
159
194
|
# Called from at_exit block
|
160
195
|
#
|
161
196
|
def run_exit_tasks!
|
197
|
+
set_exit_exception
|
198
|
+
|
162
199
|
exit_status = SimpleCov.exit_status_from_exception
|
163
200
|
|
164
201
|
SimpleCov.at_exit.call
|
@@ -170,7 +207,7 @@ module SimpleCov
|
|
170
207
|
# Force exit with stored status (see github issue #5)
|
171
208
|
# unless it's nil or 0 (see github issue #281)
|
172
209
|
if exit_status&.positive?
|
173
|
-
$stderr.printf("SimpleCov failed with exit %<exit_status>d\n", :
|
210
|
+
$stderr.printf("SimpleCov failed with exit %<exit_status>d\n", exit_status: exit_status) if print_error_status
|
174
211
|
Kernel.exit exit_status
|
175
212
|
end
|
176
213
|
end
|
@@ -197,25 +234,25 @@ module SimpleCov
|
|
197
234
|
if covered_percent < SimpleCov.minimum_coverage
|
198
235
|
$stderr.printf(
|
199
236
|
"Coverage (%<covered>.2f%%) is below the expected minimum coverage (%<minimum_coverage>.2f%%).\n",
|
200
|
-
:
|
201
|
-
:
|
237
|
+
covered: covered_percent,
|
238
|
+
minimum_coverage: SimpleCov.minimum_coverage
|
202
239
|
)
|
203
240
|
SimpleCov::ExitCodes::MINIMUM_COVERAGE
|
204
241
|
elsif covered_percentages.any? { |p| p < SimpleCov.minimum_coverage_by_file }
|
205
242
|
$stderr.printf(
|
206
243
|
"File (%<file>s) is only (%<least_covered_percentage>.2f%%) covered. This is below the expected minimum coverage per file of (%<min_coverage>.2f%%).\n",
|
207
|
-
:
|
208
|
-
:
|
209
|
-
:
|
244
|
+
file: result.least_covered_file,
|
245
|
+
least_covered_percentage: covered_percentages.min,
|
246
|
+
min_coverage: SimpleCov.minimum_coverage_by_file
|
210
247
|
)
|
211
248
|
SimpleCov::ExitCodes::MINIMUM_COVERAGE
|
212
249
|
elsif (last_run = SimpleCov::LastRun.read)
|
213
|
-
coverage_diff = last_run[
|
250
|
+
coverage_diff = last_run[:result][:covered_percent] - covered_percent
|
214
251
|
if coverage_diff > SimpleCov.maximum_coverage_drop
|
215
252
|
$stderr.printf(
|
216
253
|
"Coverage has dropped by %<drop_percent>.2f%% since the last time (maximum allowed: %<max_drop>.2f%%).\n",
|
217
|
-
:
|
218
|
-
:
|
254
|
+
drop_percent: coverage_diff,
|
255
|
+
max_drop: SimpleCov.maximum_coverage_drop
|
219
256
|
)
|
220
257
|
SimpleCov::ExitCodes::MAXIMUM_COVERAGE_DROP
|
221
258
|
else
|
@@ -248,18 +285,24 @@ module SimpleCov
|
|
248
285
|
# @api private
|
249
286
|
#
|
250
287
|
def write_last_run(covered_percent)
|
251
|
-
SimpleCov::LastRun.write(:
|
288
|
+
SimpleCov::LastRun.write(result: {covered_percent: covered_percent})
|
252
289
|
end
|
253
290
|
|
254
291
|
private
|
255
292
|
|
293
|
+
def initial_setup(profile, &block)
|
294
|
+
load_profile(profile) if profile
|
295
|
+
configure(&block) if block_given?
|
296
|
+
self.running = true
|
297
|
+
end
|
298
|
+
|
256
299
|
#
|
257
300
|
# Trigger Coverage.start depends on given config coverage_criterion
|
258
301
|
#
|
259
302
|
# With Positive branch it supports all coverage measurement types
|
260
303
|
# With Negative branch it supports only line coverage measurement type
|
261
304
|
#
|
262
|
-
def
|
305
|
+
def start_coverage_measurement
|
263
306
|
# This blog post gives a good run down of the coverage criterias introduced
|
264
307
|
# in Ruby 2.5: https://blog.bigbinary.com/2018/04/11/ruby-2-5-supports-measuring-branch-and-method-coverages.html
|
265
308
|
# There is also a nice writeup of the different coverage criteria made in this
|
@@ -287,13 +330,29 @@ module SimpleCov
|
|
287
330
|
# :oneshot_lines - can not be combined with lines
|
288
331
|
# :all - same as lines + branches + methods
|
289
332
|
#
|
290
|
-
if
|
291
|
-
|
333
|
+
if coverage_start_arguments_supported?
|
334
|
+
start_coverage_with_criteria
|
292
335
|
else
|
293
336
|
Coverage.start
|
294
337
|
end
|
295
338
|
end
|
296
339
|
|
340
|
+
def start_coverage_with_criteria
|
341
|
+
start_arguments = coverage_criteria.map do |criterion|
|
342
|
+
[lookup_corresponding_ruby_coverage_name(criterion), true]
|
343
|
+
end.to_h
|
344
|
+
|
345
|
+
Coverage.start(start_arguments)
|
346
|
+
end
|
347
|
+
|
348
|
+
CRITERION_TO_RUBY_COVERAGE = {
|
349
|
+
branch: :branches,
|
350
|
+
line: :lines
|
351
|
+
}.freeze
|
352
|
+
def lookup_corresponding_ruby_coverage_name(criterion)
|
353
|
+
CRITERION_TO_RUBY_COVERAGE.fetch(criterion)
|
354
|
+
end
|
355
|
+
|
297
356
|
#
|
298
357
|
# Finds files that were to be tracked but were not loaded and initializes
|
299
358
|
# the line-by-line coverage to zero (if relevant) or nil (comments / whitespace etc).
|
@@ -15,10 +15,9 @@ module SimpleCov
|
|
15
15
|
# @return [Hash]
|
16
16
|
#
|
17
17
|
def combine(coverage_a, coverage_b)
|
18
|
-
{
|
19
|
-
|
20
|
-
|
21
|
-
}
|
18
|
+
combination = {"lines" => Combine.combine(LinesCombiner, coverage_a["lines"], coverage_b["lines"])}
|
19
|
+
combination["branches"] = Combine.combine(BranchesCombiner, coverage_a["branches"], coverage_b["branches"]) if SimpleCov.branch_coverage?
|
20
|
+
combination
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
@@ -20,30 +20,70 @@ module SimpleCov
|
|
20
20
|
# @return [Hash]
|
21
21
|
#
|
22
22
|
def combine(*results)
|
23
|
-
results.reduce({}) do |
|
24
|
-
combine_result_sets(
|
23
|
+
results.reduce({}) do |combined_results, next_result|
|
24
|
+
combine_result_sets(combined_results, next_result)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
28
|
#
|
29
29
|
# Manage combining results on files level
|
30
30
|
#
|
31
|
-
# @param [Hash]
|
32
|
-
# @param [Hash]
|
31
|
+
# @param [Hash] combined_results
|
32
|
+
# @param [Hash] result
|
33
33
|
#
|
34
34
|
# @return [Hash]
|
35
35
|
#
|
36
|
-
def combine_result_sets(
|
37
|
-
|
36
|
+
def combine_result_sets(combined_results, result)
|
37
|
+
unless correct_format?(result)
|
38
|
+
warn_wrong_format
|
39
|
+
return combined_results
|
40
|
+
end
|
41
|
+
|
42
|
+
results_files = combined_results.keys | result.keys
|
38
43
|
|
39
|
-
results_files.each_with_object({}) do |file_name,
|
40
|
-
|
41
|
-
|
42
|
-
|
44
|
+
results_files.each_with_object({}) do |file_name, file_combination|
|
45
|
+
file_combination[file_name] = combine_file_coverage(
|
46
|
+
combined_results[file_name],
|
47
|
+
result[file_name]
|
43
48
|
)
|
44
49
|
end
|
45
50
|
end
|
46
51
|
|
52
|
+
# We might start a run of a new simplecov version with a new format stored while
|
53
|
+
# there is still a recent file like this lying around. If it's recent enough (
|
54
|
+
# see merge_timeout) it will end up here. In order not to crash against this
|
55
|
+
# we need to do some basic checking of the format of data we expect and
|
56
|
+
# otherwise ignore it. See #820
|
57
|
+
#
|
58
|
+
# Currently correct format is:
|
59
|
+
# { file_path_string => {coverage_criterion => coverage_date}}
|
60
|
+
#
|
61
|
+
# Internal use/reliance only.
|
62
|
+
def correct_format?(result)
|
63
|
+
result.empty? || matches_current_format?(result)
|
64
|
+
end
|
65
|
+
|
66
|
+
def matches_current_format?(result)
|
67
|
+
# I so wish I could already use pattern matching
|
68
|
+
key, data = result.first
|
69
|
+
|
70
|
+
key.is_a?(String) && second_level_choice_of_criterion?(data)
|
71
|
+
end
|
72
|
+
|
73
|
+
SECOND_LEVEL_KEYS = %w[lines branches].freeze
|
74
|
+
def second_level_choice_of_criterion?(data)
|
75
|
+
second_level_key, = data.first
|
76
|
+
|
77
|
+
SECOND_LEVEL_KEYS.member?(second_level_key)
|
78
|
+
end
|
79
|
+
|
80
|
+
def warn_wrong_format
|
81
|
+
warn "Merging results, encountered an incorrectly formatted value. "\
|
82
|
+
"This value was ignored.\nIf you just upgraded simplecov this is "\
|
83
|
+
"likely due to a changed file format. If this happens again please "\
|
84
|
+
"file a bug. https://github.com/colszowka/simplecov/issues"
|
85
|
+
end
|
86
|
+
|
47
87
|
#
|
48
88
|
# Combine two files coverage results
|
49
89
|
#
|
@@ -313,7 +313,7 @@ module SimpleCov
|
|
313
313
|
# * :line - coverage based on lines aka has this line been executed?
|
314
314
|
# * :branch - coverage based on branches aka has this branch (think conditions) been executed?
|
315
315
|
#
|
316
|
-
# If not set the default is
|
316
|
+
# If not set the default is `:line`
|
317
317
|
#
|
318
318
|
# @param [Symbol] criterion
|
319
319
|
#
|
@@ -335,15 +335,31 @@ module SimpleCov
|
|
335
335
|
@coverage_criteria ||= Set[DEFAULT_COVERAGE_CRITERION]
|
336
336
|
end
|
337
337
|
|
338
|
+
def coverage_criterion_enabled?(criterion)
|
339
|
+
coverage_criteria.member?(criterion)
|
340
|
+
end
|
341
|
+
|
342
|
+
def clear_coverage_criteria
|
343
|
+
@coverage_criteria = nil
|
344
|
+
end
|
345
|
+
|
338
346
|
def branch_coverage?
|
339
|
-
branch_coverage_supported? &&
|
347
|
+
branch_coverage_supported? && coverage_criterion_enabled?(:branch)
|
340
348
|
end
|
341
349
|
|
342
|
-
def
|
343
|
-
|
344
|
-
|
350
|
+
def coverage_start_arguments_supported?
|
351
|
+
# safe to cache as within one process this value should never
|
352
|
+
# change
|
353
|
+
return @coverage_start_arguments_supported if defined?(@coverage_start_arguments_supported)
|
354
|
+
|
355
|
+
@coverage_start_arguments_supported = begin
|
356
|
+
require "coverage"
|
357
|
+
!Coverage.method(:start).arity.zero?
|
358
|
+
end
|
345
359
|
end
|
346
360
|
|
361
|
+
alias branch_coverage_supported? coverage_start_arguments_supported?
|
362
|
+
|
347
363
|
private
|
348
364
|
|
349
365
|
def raise_if_criterion_unsupported(criterion)
|
data/lib/simplecov/defaults.rb
CHANGED
@@ -25,7 +25,9 @@ at_exit do
|
|
25
25
|
# If we are in a different process than called start, don't interfere.
|
26
26
|
next if SimpleCov.pid != Process.pid
|
27
27
|
|
28
|
-
SimpleCov
|
28
|
+
# If SimpleCov is no longer running then don't run exit tasks
|
29
|
+
next unless SimpleCov.running
|
30
|
+
|
29
31
|
SimpleCov.run_exit_tasks!
|
30
32
|
end
|
31
33
|
|
data/lib/simplecov/last_run.rb
CHANGED
data/lib/simplecov/result.rb
CHANGED
@@ -28,7 +28,7 @@ module SimpleCov
|
|
28
28
|
def initialize(original_result)
|
29
29
|
@original_result = original_result.freeze
|
30
30
|
@files = SimpleCov::FileList.new(original_result.map do |filename, coverage|
|
31
|
-
SimpleCov::SourceFile.new(filename, JSON.parse(JSON.dump(coverage)
|
31
|
+
SimpleCov::SourceFile.new(filename, JSON.parse(JSON.dump(coverage))) if File.file?(filename)
|
32
32
|
end.compact.sort_by(&:filename))
|
33
33
|
filter!
|
34
34
|
end
|
@@ -61,35 +61,25 @@ module SimpleCov
|
|
61
61
|
|
62
62
|
# Returns a hash representation of this Result that can be used for marshalling it into JSON
|
63
63
|
def to_hash
|
64
|
-
{
|
64
|
+
{
|
65
|
+
command_name => {
|
66
|
+
"coverage" => coverage,
|
67
|
+
"timestamp" => created_at.to_i
|
68
|
+
}
|
69
|
+
}
|
65
70
|
end
|
66
71
|
|
67
72
|
# Loads a SimpleCov::Result#to_hash dump
|
68
73
|
def self.from_hash(hash)
|
69
74
|
command_name, data = hash.first
|
70
75
|
|
71
|
-
result = SimpleCov::Result.new(
|
72
|
-
symbolize_names_of_coverage_results(data["coverage"])
|
73
|
-
)
|
76
|
+
result = SimpleCov::Result.new(data["coverage"])
|
74
77
|
|
75
78
|
result.command_name = command_name
|
76
79
|
result.created_at = Time.at(data["timestamp"])
|
77
80
|
result
|
78
81
|
end
|
79
82
|
|
80
|
-
# Manage symbolize the keys of coverage hash.
|
81
|
-
# JSON.parse gives coverage hash with stringified keys what breaks some logics
|
82
|
-
# inside the process that expects them as symboles.
|
83
|
-
#
|
84
|
-
# @return [Hash]
|
85
|
-
def self.symbolize_names_of_coverage_results(coverage_data)
|
86
|
-
coverage_data.each_with_object({}) do |(file_name, file_coverage_result), coverage_results|
|
87
|
-
coverage_results[file_name] = file_coverage_result.each_with_object({}) do |(k, v), cov_elem|
|
88
|
-
cov_elem[k.to_sym] = v
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
83
|
private
|
94
84
|
|
95
85
|
def coverage
|
@@ -20,7 +20,7 @@ module SimpleCov
|
|
20
20
|
|
21
21
|
result.each_with_object({}) do |(file_name, cover_statistic), adapted_result|
|
22
22
|
if cover_statistic.is_a?(Array)
|
23
|
-
adapted_result.merge!(file_name => {
|
23
|
+
adapted_result.merge!(file_name => {"lines" => cover_statistic})
|
24
24
|
else
|
25
25
|
adapted_result.merge!(file_name => cover_statistic)
|
26
26
|
end
|
@@ -62,11 +62,17 @@ module SimpleCov
|
|
62
62
|
results
|
63
63
|
end
|
64
64
|
|
65
|
+
def merge_and_store(*results)
|
66
|
+
result = merge_results(*results)
|
67
|
+
store_result(result) if result
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
65
71
|
# Merge two or more SimpleCov::Results into a new one with merged
|
66
72
|
# coverage data and the command_name for the result consisting of a join
|
67
73
|
# on all source result's names
|
68
74
|
def merge_results(*results)
|
69
|
-
parsed_results = JSON.parse(JSON.dump(results.map(&:original_result))
|
75
|
+
parsed_results = JSON.parse(JSON.dump(results.map(&:original_result)))
|
70
76
|
combined_result = SimpleCov::Combine::ResultsCombiner.combine(*parsed_results)
|
71
77
|
result = SimpleCov::Result.new(combined_result)
|
72
78
|
# Specify the command name
|
@@ -19,10 +19,10 @@ module SimpleCov
|
|
19
19
|
lines = File.foreach(absolute_path)
|
20
20
|
|
21
21
|
{
|
22
|
-
|
22
|
+
"lines" => LinesClassifier.new.classify(lines),
|
23
23
|
# we don't want to parse branches ourselves...
|
24
24
|
# requiring files can have side effects and we don't want to trigger that
|
25
|
-
|
25
|
+
"branches" => {}
|
26
26
|
}
|
27
27
|
end
|
28
28
|
end
|
@@ -12,7 +12,7 @@ module SimpleCov
|
|
12
12
|
attr_reader :coverage
|
13
13
|
|
14
14
|
def initialize(filename, coverage)
|
15
|
-
@filename = filename
|
15
|
+
@filename = filename
|
16
16
|
@coverage = coverage
|
17
17
|
end
|
18
18
|
|
@@ -64,9 +64,9 @@ module SimpleCov
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def build_lines
|
67
|
-
coverage_exceeding_source_warn if coverage[
|
67
|
+
coverage_exceeding_source_warn if coverage["lines"].size > src.size
|
68
68
|
lines = src.map.with_index(1) do |src, i|
|
69
|
-
SimpleCov::SourceFile::Line.new(src, i, coverage[
|
69
|
+
SimpleCov::SourceFile::Line.new(src, i, coverage["lines"][i - 1])
|
70
70
|
end
|
71
71
|
process_skipped_lines(lines)
|
72
72
|
end
|
@@ -97,7 +97,7 @@ module SimpleCov
|
|
97
97
|
|
98
98
|
# Warning to identify condition from Issue #56
|
99
99
|
def coverage_exceeding_source_warn
|
100
|
-
warn "Warning: coverage data provided by Coverage [#{coverage[
|
100
|
+
warn "Warning: coverage data provided by Coverage [#{coverage['lines'].size}] exceeds number of lines in #{filename} [#{src.size}]"
|
101
101
|
end
|
102
102
|
|
103
103
|
# Access SimpleCov::SourceFile::Line source lines by line number
|
@@ -168,7 +168,7 @@ module SimpleCov
|
|
168
168
|
# @return [Array]
|
169
169
|
#
|
170
170
|
def build_branches
|
171
|
-
coverage_branch_data = coverage.fetch(
|
171
|
+
coverage_branch_data = coverage.fetch("branches", {})
|
172
172
|
branches = coverage_branch_data.flat_map do |condition, coverage_branches|
|
173
173
|
build_branches_from(condition, coverage_branches)
|
174
174
|
end
|
@@ -187,7 +187,7 @@ module SimpleCov
|
|
187
187
|
end
|
188
188
|
|
189
189
|
# Since we are dumping to and loading from JSON, and we have arrays as keys those
|
190
|
-
# don't make their way back to us intact e.g. just as a string
|
190
|
+
# don't make their way back to us intact e.g. just as a string
|
191
191
|
#
|
192
192
|
# We should probably do something different here, but as it stands these are
|
193
193
|
# our data structures that we write so eval isn't _too_ bad.
|
@@ -199,9 +199,8 @@ module SimpleCov
|
|
199
199
|
# put them through here.
|
200
200
|
return structure if structure.is_a?(Array)
|
201
201
|
|
202
|
-
# as of right now the keys are still symbolized
|
203
202
|
# rubocop:disable Security/Eval
|
204
|
-
eval structure
|
203
|
+
eval structure
|
205
204
|
# rubocop:enable Security/Eval
|
206
205
|
end
|
207
206
|
|
@@ -211,56 +210,26 @@ module SimpleCov
|
|
211
210
|
# [:then, 4, 6, 6, 6, 10]
|
212
211
|
#
|
213
212
|
# which is [type, id, start_line, start_col, end_line, end_col]
|
214
|
-
|
213
|
+
_condition_type, _condition_id, condition_start_line, * = restore_ruby_data_structure(condition)
|
215
214
|
|
216
|
-
branches
|
217
|
-
|
218
|
-
|
219
|
-
|
215
|
+
branches.map do |branch_data, hit_count|
|
216
|
+
branch_data = restore_ruby_data_structure(branch_data)
|
217
|
+
build_branch(branch_data, hit_count, condition_start_line)
|
218
|
+
end
|
220
219
|
end
|
221
220
|
|
222
|
-
def build_branch(branch_data, hit_count, condition_start_line
|
223
|
-
type,
|
221
|
+
def build_branch(branch_data, hit_count, condition_start_line)
|
222
|
+
type, _id, start_line, _start_col, end_line, _end_col = branch_data
|
224
223
|
|
225
224
|
SourceFile::Branch.new(
|
226
|
-
# rubocop these are keyword args please let me keep them, thank you
|
227
|
-
# rubocop:disable Style/HashSyntax
|
228
225
|
start_line: start_line,
|
229
226
|
end_line: end_line,
|
230
227
|
coverage: hit_count,
|
231
228
|
inline: start_line == condition_start_line,
|
232
|
-
|
233
|
-
# rubocop:enable Style/HashSyntax
|
229
|
+
type: type
|
234
230
|
)
|
235
231
|
end
|
236
232
|
|
237
|
-
def ignore_branch?(branch_data, condition_type, condition_start_line)
|
238
|
-
branch_type = branch_data[0]
|
239
|
-
branch_start_line = branch_data[2]
|
240
|
-
|
241
|
-
# branch coverage always reports case to be with an else branch even when
|
242
|
-
# there is no else branch to be covered, it's noticable by the reported start
|
243
|
-
# line being the same as that of the condition/case
|
244
|
-
condition_type == :case &&
|
245
|
-
branch_type == :else &&
|
246
|
-
condition_start_line == branch_start_line
|
247
|
-
end
|
248
|
-
|
249
|
-
#
|
250
|
-
# Branch is positive or negative.
|
251
|
-
# For `case` conditions, `when` always supposed as positive branch.
|
252
|
-
# For `if, else` conditions:
|
253
|
-
# coverage returns matrices ex: [:if, 0,..] => {[:then, 1,..], [:else, 2,..]},
|
254
|
-
# positive branch always has id equals to condition id incremented by 1.
|
255
|
-
#
|
256
|
-
# @return [Boolean]
|
257
|
-
#
|
258
|
-
def positive_branch?(condition_id, branch_id, branch_type)
|
259
|
-
return true if branch_type == :when
|
260
|
-
|
261
|
-
branch_id == (1 + condition_id)
|
262
|
-
end
|
263
|
-
|
264
233
|
#
|
265
234
|
# Select the covered branches
|
266
235
|
# Here we user tree schema because some conditions like case may have additional
|
@@ -293,7 +262,7 @@ module SimpleCov
|
|
293
262
|
# @return [Boolean]
|
294
263
|
#
|
295
264
|
def line_with_missed_branch?(line_number)
|
296
|
-
branches_for_line(line_number).select { |
|
265
|
+
branches_for_line(line_number).select { |_type, count| count.zero? }.any?
|
297
266
|
end
|
298
267
|
|
299
268
|
#
|
@@ -6,15 +6,15 @@ module SimpleCov
|
|
6
6
|
# Representing single branch that has been detected in coverage report.
|
7
7
|
# Give us support methods that handle needed calculations.
|
8
8
|
class Branch
|
9
|
-
attr_reader :start_line, :end_line, :coverage
|
9
|
+
attr_reader :start_line, :end_line, :coverage, :type
|
10
10
|
|
11
11
|
# rubocop:disable Metrics/ParameterLists
|
12
|
-
def initialize(start_line:, end_line:, coverage:, inline:,
|
12
|
+
def initialize(start_line:, end_line:, coverage:, inline:, type:)
|
13
13
|
@start_line = start_line
|
14
14
|
@end_line = end_line
|
15
15
|
@coverage = coverage
|
16
16
|
@inline = inline
|
17
|
-
@
|
17
|
+
@type = type
|
18
18
|
@skipped = false
|
19
19
|
end
|
20
20
|
# rubocop:enable Metrics/ParameterLists
|
@@ -23,19 +23,6 @@ module SimpleCov
|
|
23
23
|
@inline
|
24
24
|
end
|
25
25
|
|
26
|
-
def positive?
|
27
|
-
@positive
|
28
|
-
end
|
29
|
-
|
30
|
-
#
|
31
|
-
# Branch is negative
|
32
|
-
#
|
33
|
-
# @return [Boolean]
|
34
|
-
#
|
35
|
-
def negative?
|
36
|
-
!positive?
|
37
|
-
end
|
38
|
-
|
39
26
|
#
|
40
27
|
# Return true if there is relevant count defined > 0
|
41
28
|
#
|
@@ -54,15 +41,6 @@ module SimpleCov
|
|
54
41
|
!skipped? && coverage.zero?
|
55
42
|
end
|
56
43
|
|
57
|
-
#
|
58
|
-
# Return the sign depends on branch is positive or negative
|
59
|
-
#
|
60
|
-
# @return [String]
|
61
|
-
#
|
62
|
-
def badge
|
63
|
-
positive? ? "+" : "-"
|
64
|
-
end
|
65
|
-
|
66
44
|
# The line on which we want to report the coverage
|
67
45
|
#
|
68
46
|
# Usually we choose the line above the start of the branch (so that it shows up
|
@@ -99,7 +77,7 @@ module SimpleCov
|
|
99
77
|
# @return [Array]
|
100
78
|
#
|
101
79
|
def report
|
102
|
-
[
|
80
|
+
[type, coverage]
|
103
81
|
end
|
104
82
|
end
|
105
83
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module SimpleCov
|
4
4
|
#
|
5
|
-
#
|
5
|
+
# Select the files that related to working scope directory of SimpleCov
|
6
6
|
#
|
7
7
|
module UselessResultsRemover
|
8
8
|
ROOT_REGX = /\A#{Regexp.escape(SimpleCov.root + File::SEPARATOR)}/io.freeze
|
data/lib/simplecov/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simplecov
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.18.0.
|
4
|
+
version: 0.18.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christoph Olszowka
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-01-
|
11
|
+
date: 2020-01-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: docile
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.11.0.
|
33
|
+
version: 0.11.0.beta2
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.11.0.
|
40
|
+
version: 0.11.0.beta2
|
41
41
|
description: Code coverage for Ruby with a powerful configuration library and automatic
|
42
42
|
merging of coverage across test suites
|
43
43
|
email:
|
@@ -95,9 +95,9 @@ licenses:
|
|
95
95
|
metadata:
|
96
96
|
bug_tracker_uri: https://github.com/colszowka/simplecov/issues
|
97
97
|
changelog_uri: https://github.com/colszowka/simplecov/blob/master/CHANGELOG.md
|
98
|
-
documentation_uri: https://www.rubydoc.info/gems/simplecov/0.18.0.
|
98
|
+
documentation_uri: https://www.rubydoc.info/gems/simplecov/0.18.0.beta2
|
99
99
|
mailing_list_uri: https://groups.google.com/forum/#!forum/simplecov
|
100
|
-
source_code_uri: https://github.com/colszowka/simplecov/tree/v0.18.0.
|
100
|
+
source_code_uri: https://github.com/colszowka/simplecov/tree/v0.18.0.beta2
|
101
101
|
post_install_message:
|
102
102
|
rdoc_options: []
|
103
103
|
require_paths:
|