simplecov 0.18.0.beta1 → 0.18.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|