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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8dd6ab6b1c33e8b2503dc00691a8ae500ae0caf885fc2dba52bbe102d696d926
4
- data.tar.gz: 41c70724c0beb18bd66f665cb078a8b9cf95d1dbb770bf1eb0601156c12370e0
3
+ metadata.gz: eeee06c5cbeaf6c89000a43641f7a6163d9b267d145698e742089385eae6e2b8
4
+ data.tar.gz: 76e7182adc3c8156e021d780618733f6237a81723656f0123b51abf34a63e891
5
5
  SHA512:
6
- metadata.gz: ba1dcb50ce7ef6765a9f519bda006388d587c67cd103bcf6d0f4bd4d4427ebef240de13772e8925f62d70dd232310bd705b66fbda1c39c25444dcd329b9dedc1
7
- data.tar.gz: cc1160ba31aa5ecdcb46a255e3147e78f649789d542d1363343fec803ec9c5c96759272990ba67ceb75a0a07116325f962a69354d8a01477a905b491bba86275
6
+ metadata.gz: e5e785e01ff4bf53c9cbdbeaeb7cc5925265e2ec9cacecb9865261150eed13b8c59c43d840588eb6baa0565ce510c74891f535f02bb1db42d2eeea4e61b3cd54
7
+ data.tar.gz: d8f29ed7d8ecf8a01d9fcd843a0c2a9845f022a690c8c7096c23077f7e3c2488fce290e099e70083ee44e37d1bb05f1535c2ec1a70b6952929ab92857b38a339
@@ -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 official support for all EOL'ed rubies meaning we only officially support 2.4+ - older rubies might still work but are not guaranteed to do so. Older release should still work. (thanks [@deivid-rodriguez](https://github.com/deivid-rodriguez))
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 with line coverage as just evaluating the condition marks it as covered.
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
- In the HTML report the lines of code will be annotated like `hit_count, positive_or_negative_branch`:
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
- * `2, +` - the positive branch was executed twice
316
- * `0, -` - the negative branch was never executed
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 (coverage_path)/.resultset.json. Those results will then
465
- be automatically merged when generating the result, so when coverage is set up properly for Cucumber and your
466
- unit / functional / integration tests, all of those test suites will be taken into account when building the
467
- coverage report.
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
- Of course, your cached coverage data is likely to become invalid at some point. Thus, result sets that are older than
526
- `SimpleCov.merge_timeout` will not be used any more. By default, the timeout is 600 seconds (10 minutes), and you can
527
- raise (or lower) it by specifying `SimpleCov.merge_timeout 3600` (1 hour), or, inside a configure/start block, with
528
- just `merge_timeout 3600`.
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
- You can deactivate merging altogether with `SimpleCov.use_merging false`.
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
 
@@ -46,13 +46,48 @@ module SimpleCov
46
46
  #
47
47
  def start(profile = nil, &block)
48
48
  require "coverage"
49
- load_profile(profile) if profile
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
- start_coverage_measurment
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", :exit_status => exit_status) if print_error_status
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
- :covered => covered_percent,
201
- :minimum_coverage => SimpleCov.minimum_coverage
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
- :file => result.least_covered_file,
208
- :least_covered_percentage => covered_percentages.min,
209
- :min_coverage => SimpleCov.minimum_coverage_by_file
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["result"]["covered_percent"] - covered_percent
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
- :drop_percent => coverage_diff,
218
- :max_drop => SimpleCov.maximum_coverage_drop
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(:result => {:covered_percent => covered_percent})
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 start_coverage_measurment
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 branch_coverage?
291
- Coverage.start(:all)
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
- :lines => Combine.combine(LinesCombiner, coverage_a[:lines], coverage_b[:lines]),
20
- :branches => Combine.combine(BranchesCombiner, coverage_a[:branches], coverage_b[:branches])
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 |result, next_result|
24
- combine_result_sets(result, next_result)
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] result_a
32
- # @param [Hash] result_b
31
+ # @param [Hash] combined_results
32
+ # @param [Hash] result
33
33
  #
34
34
  # @return [Hash]
35
35
  #
36
- def combine_result_sets(result_a, result_b)
37
- results_files = result_a.keys | result_b.keys
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, combined_results|
40
- combined_results[file_name] = combine_file_coverage(
41
- result_a[file_name],
42
- result_b[file_name]
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 is `:line`
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? && coverage_criteria.member?(:branch)
347
+ branch_coverage_supported? && coverage_criterion_enabled?(:branch)
340
348
  end
341
349
 
342
- def branch_coverage_supported?
343
- require "coverage"
344
- !Coverage.method(:start).arity.zero?
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)
@@ -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.set_exit_exception
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
 
@@ -15,7 +15,7 @@ module SimpleCov
15
15
  json = File.read(last_run_path)
16
16
  return nil if json.strip.empty?
17
17
 
18
- JSON.parse(json)
18
+ JSON.parse(json, symbolize_names: true)
19
19
  end
20
20
 
21
21
  def write(json)
@@ -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), :symbolize_names => true)) if File.file?(filename.to_s)
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
- {command_name => {"coverage" => coverage, "timestamp" => created_at.to_i}}
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 => {:lines => cover_statistic})
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)), :symbolize_names => true)
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
- :lines => LinesClassifier.new.classify(lines),
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
- :branches => {}
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.to_s
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[:lines].size > src.size
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[:lines][i - 1])
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[:lines].size}] exceeds number of lines in #{filename} [#{src.size}]"
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(:branches, {})
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 or a symbol (currently keys are symbolized).
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.to_s
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
- condition_type, condition_id, condition_start_line, * = restore_ruby_data_structure(condition)
213
+ _condition_type, _condition_id, condition_start_line, * = restore_ruby_data_structure(condition)
215
214
 
216
- branches
217
- .map { |branch_data, hit_count| [restore_ruby_data_structure(branch_data), hit_count] }
218
- .reject { |branch_data, _hit_count| ignore_branch?(branch_data, condition_type, condition_start_line) }
219
- .map { |branch_data, hit_count| build_branch(branch_data, hit_count, condition_start_line, condition_id) }
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, condition_id)
223
- type, id, start_line, _start_col, end_line, _end_col = branch_data
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
- positive: positive_branch?(condition_id, id, type)
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 { |count, _sign| count.zero? }.any?
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:, positive:)
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
- @positive = positive
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
- [coverage, badge]
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
- # Selection the files that related to working scope directory of SimpleCov
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleCov
4
- VERSION = "0.18.0.beta1"
4
+ VERSION = "0.18.0.beta2"
5
5
  end
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.beta1
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-05 00:00:00.000000000 Z
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.beta1
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.beta1
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.beta1
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.beta1
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: