simplecov 0.22.0 → 1.0.2

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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +1058 -508
  4. data/doc/alternate-formatters.md +0 -5
  5. data/doc/commercial-services.md +5 -5
  6. data/exe/simplecov +11 -0
  7. data/lib/minitest/simplecov_plugin.rb +13 -5
  8. data/lib/simplecov/autostart.rb +11 -0
  9. data/lib/simplecov/cli/clean.rb +47 -0
  10. data/lib/simplecov/cli/coverage.rb +93 -0
  11. data/lib/simplecov/cli/diff.rb +152 -0
  12. data/lib/simplecov/cli/dotfile.rb +105 -0
  13. data/lib/simplecov/cli/merge.rb +118 -0
  14. data/lib/simplecov/cli/open.rb +50 -0
  15. data/lib/simplecov/cli/report.rb +89 -0
  16. data/lib/simplecov/cli/run.rb +36 -0
  17. data/lib/simplecov/cli/serve.rb +149 -0
  18. data/lib/simplecov/cli/uncovered.rb +108 -0
  19. data/lib/simplecov/cli.rb +150 -0
  20. data/lib/simplecov/color.rb +79 -0
  21. data/lib/simplecov/combine/branches_combiner.rb +28 -5
  22. data/lib/simplecov/combine/files_combiner.rb +47 -1
  23. data/lib/simplecov/combine/lines_combiner.rb +19 -17
  24. data/lib/simplecov/combine/methods_combiner.rb +49 -0
  25. data/lib/simplecov/combine/results_combiner.rb +7 -5
  26. data/lib/simplecov/command_guesser.rb +46 -32
  27. data/lib/simplecov/configuration/coverage.rb +175 -0
  28. data/lib/simplecov/configuration/coverage_criteria.rb +158 -0
  29. data/lib/simplecov/configuration/filters.rb +197 -0
  30. data/lib/simplecov/configuration/formatting.rb +129 -0
  31. data/lib/simplecov/configuration/ignored_entries.rb +63 -0
  32. data/lib/simplecov/configuration/merging.rb +164 -0
  33. data/lib/simplecov/configuration/thresholds.rb +178 -0
  34. data/lib/simplecov/configuration.rb +105 -412
  35. data/lib/simplecov/coverage_statistics.rb +15 -9
  36. data/lib/simplecov/coverage_violations.rb +149 -0
  37. data/lib/simplecov/defaults.rb +29 -22
  38. data/lib/simplecov/deprecation.rb +45 -0
  39. data/lib/simplecov/directive.rb +167 -0
  40. data/lib/simplecov/exit_codes/exit_code_handling.rb +8 -2
  41. data/lib/simplecov/exit_codes/maximum_coverage_drop_check.rb +19 -57
  42. data/lib/simplecov/exit_codes/maximum_overall_coverage_check.rb +45 -0
  43. data/lib/simplecov/exit_codes/minimum_coverage_by_file_check.rb +17 -27
  44. data/lib/simplecov/exit_codes/minimum_coverage_by_group_check.rb +41 -0
  45. data/lib/simplecov/exit_codes/minimum_overall_coverage_check.rb +38 -21
  46. data/lib/simplecov/exit_codes.rb +15 -0
  47. data/lib/simplecov/exit_handling.rb +158 -0
  48. data/lib/simplecov/file_list.rb +70 -19
  49. data/lib/simplecov/filter.rb +69 -24
  50. data/lib/simplecov/formatter/base.rb +102 -0
  51. data/lib/simplecov/formatter/html_formatter/public/application.css +1 -0
  52. data/lib/simplecov/formatter/html_formatter/public/application.js +18 -0
  53. data/lib/simplecov/formatter/html_formatter/public/favicon_green.png +0 -0
  54. data/lib/simplecov/formatter/html_formatter/public/favicon_red.png +0 -0
  55. data/lib/simplecov/formatter/html_formatter/public/favicon_yellow.png +0 -0
  56. data/lib/simplecov/formatter/html_formatter/public/index.html +56 -0
  57. data/lib/simplecov/formatter/html_formatter.rb +85 -0
  58. data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +90 -0
  59. data/lib/simplecov/formatter/json_formatter/result_hash_formatter.rb +128 -0
  60. data/lib/simplecov/formatter/json_formatter/source_file_formatter.rb +99 -0
  61. data/lib/simplecov/formatter/json_formatter.rb +89 -0
  62. data/lib/simplecov/formatter/multi_formatter.rb +11 -7
  63. data/lib/simplecov/formatter/simple_formatter.rb +11 -11
  64. data/lib/simplecov/formatter.rb +4 -0
  65. data/lib/simplecov/last_run.rb +10 -3
  66. data/lib/simplecov/lines_classifier.rb +25 -13
  67. data/lib/simplecov/load_global_config.rb +9 -4
  68. data/lib/simplecov/parallel_adapters/base.rb +61 -0
  69. data/lib/simplecov/parallel_adapters/generic.rb +44 -0
  70. data/lib/simplecov/parallel_adapters/parallel_tests.rb +93 -0
  71. data/lib/simplecov/parallel_adapters.rb +83 -0
  72. data/lib/simplecov/parallel_coordination.rb +129 -0
  73. data/lib/simplecov/process.rb +52 -12
  74. data/lib/simplecov/profiles/bundler_filter.rb +1 -1
  75. data/lib/simplecov/profiles/hidden_filter.rb +1 -1
  76. data/lib/simplecov/profiles/rails.rb +24 -10
  77. data/lib/simplecov/profiles/root_filter.rb +6 -5
  78. data/lib/simplecov/profiles/strict.rb +32 -0
  79. data/lib/simplecov/profiles/test_frameworks.rb +1 -4
  80. data/lib/simplecov/profiles.rb +32 -3
  81. data/lib/simplecov/result/missing_source_files_reporter.rb +49 -0
  82. data/lib/simplecov/result/source_file_builder.rb +51 -0
  83. data/lib/simplecov/result.rb +108 -19
  84. data/lib/simplecov/result_adapter.rb +105 -8
  85. data/lib/simplecov/result_merger/legacy_format_adapter.rb +28 -0
  86. data/lib/simplecov/result_merger/resultset_file.rb +38 -0
  87. data/lib/simplecov/result_merger/resultset_store.rb +50 -0
  88. data/lib/simplecov/result_merger.rb +59 -91
  89. data/lib/simplecov/result_processing.rb +179 -0
  90. data/lib/simplecov/simulate_coverage.rb +54 -8
  91. data/lib/simplecov/source_file/branch.rb +1 -3
  92. data/lib/simplecov/source_file/branch_builder.rb +114 -0
  93. data/lib/simplecov/source_file/builder_context.rb +28 -0
  94. data/lib/simplecov/source_file/line.rb +9 -4
  95. data/lib/simplecov/source_file/line_builder.rb +43 -0
  96. data/lib/simplecov/source_file/method.rb +52 -0
  97. data/lib/simplecov/source_file/method_builder.rb +60 -0
  98. data/lib/simplecov/source_file/ruby_data_parser.rb +88 -0
  99. data/lib/simplecov/source_file/skip_chunks.rb +75 -0
  100. data/lib/simplecov/source_file/source_loader.rb +63 -0
  101. data/lib/simplecov/source_file/statistics.rb +57 -0
  102. data/lib/simplecov/source_file.rb +66 -232
  103. data/lib/simplecov/static_coverage_extractor/condition_folding.rb +49 -0
  104. data/lib/simplecov/static_coverage_extractor/location_conventions.rb +247 -0
  105. data/lib/simplecov/static_coverage_extractor/method_collector.rb +55 -0
  106. data/lib/simplecov/static_coverage_extractor/value_position.rb +82 -0
  107. data/lib/simplecov/static_coverage_extractor/visitor.rb +196 -0
  108. data/lib/simplecov/static_coverage_extractor.rb +110 -0
  109. data/lib/simplecov/useless_results_remover.rb +16 -7
  110. data/lib/simplecov/version.rb +1 -1
  111. data/lib/simplecov-html.rb +4 -0
  112. data/lib/simplecov.rb +178 -380
  113. data/lib/simplecov_json_formatter.rb +4 -0
  114. data/schemas/coverage-v1.0.schema.json +306 -0
  115. data/schemas/coverage.schema.json +306 -0
  116. data/sig/simplecov.rbs +1638 -0
  117. metadata +94 -57
  118. data/CHANGELOG.md +0 -191
  119. data/lib/simplecov/default_formatter.rb +0 -20
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SimpleCov
4
+ # Coverage threshold configuration: `minimum_coverage`,
5
+ # `maximum_coverage`, `expected_coverage`, `maximum_coverage_drop`,
6
+ # `minimum_coverage_by_file`, `minimum_coverage_by_group`,
7
+ # `refuse_coverage_drop`, and friends.
8
+ module Configuration
9
+ #
10
+ # Defines the minimum overall coverage required for the testsuite to pass.
11
+ # Returns non-zero if the current coverage is below this threshold.
12
+ # Default is 0% (disabled).
13
+ #
14
+ def minimum_coverage(coverage = nil)
15
+ return @minimum_coverage ||= {} unless coverage
16
+
17
+ coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
18
+ raise_on_invalid_coverage(coverage, "minimum_coverage")
19
+ @minimum_coverage = coverage
20
+ end
21
+
22
+ def raise_on_invalid_coverage(coverage, coverage_setting)
23
+ coverage.each_key { |criterion| raise_if_criterion_disabled(criterion) }
24
+ coverage.each_value do |percent|
25
+ minimum_possible_coverage_exceeded(coverage_setting) if percent && percent > 100
26
+ end
27
+ end
28
+
29
+ #
30
+ # Defines the maximum overall coverage allowed for the testsuite to
31
+ # pass. Useful paired with `minimum_coverage` (or via
32
+ # `expected_coverage`) to pin coverage to an exact value, so an
33
+ # unexpected jump up fails the build. See #187.
34
+ #
35
+ def maximum_coverage(coverage = nil)
36
+ return @maximum_coverage ||= {} unless coverage
37
+
38
+ coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
39
+ raise_on_invalid_coverage(coverage, "maximum_coverage")
40
+ @maximum_coverage = coverage
41
+ end
42
+
43
+ #
44
+ # Pins the suite to an exact coverage figure by setting both
45
+ # `minimum_coverage` and `maximum_coverage`. See #187.
46
+ #
47
+ def expected_coverage(coverage = nil)
48
+ return minimum_coverage if coverage.nil?
49
+
50
+ minimum_coverage(coverage)
51
+ maximum_coverage(coverage)
52
+ end
53
+
54
+ #
55
+ # Defines the maximum coverage drop at once allowed for the
56
+ # testsuite to pass. Default is 100% (disabled).
57
+ #
58
+ def maximum_coverage_drop(coverage_drop = nil)
59
+ return @maximum_coverage_drop ||= {} unless coverage_drop
60
+
61
+ coverage_drop = {primary_coverage => coverage_drop} if coverage_drop.is_a?(Numeric)
62
+ raise_on_invalid_coverage(coverage_drop, "maximum_coverage_drop")
63
+ @maximum_coverage_drop = coverage_drop
64
+ end
65
+
66
+ #
67
+ # Defines the minimum coverage per file required for the testsuite
68
+ # to pass. Accepts a Numeric (global threshold on the primary
69
+ # criterion), a Symbol-keyed Hash (per-criterion globals), or a
70
+ # Hash mixing Symbol keys with String / Regexp keys to declare
71
+ # per-path overrides. See README and #575.
72
+ #
73
+ def minimum_coverage_by_file(coverage = nil)
74
+ return @minimum_coverage_by_file ||= {} unless coverage
75
+
76
+ coverage = {primary_coverage => coverage} if coverage.is_a?(Numeric)
77
+ defaults, overrides = partition_per_file_thresholds(coverage)
78
+
79
+ SimpleCov::Deprecation.warn("`SimpleCov.minimum_coverage_by_file` is deprecated. " \
80
+ "Replace it with:\n#{per_file_coverage_replacement(defaults, overrides)}")
81
+
82
+ raise_on_invalid_coverage(defaults, "minimum_coverage_by_file")
83
+ overrides.each_value { |criteria| raise_on_invalid_coverage(criteria, "minimum_coverage_by_file") }
84
+
85
+ @minimum_coverage_by_file = defaults
86
+ @minimum_coverage_by_file_overrides = overrides
87
+ end
88
+
89
+ # Returns the per-path overrides set via `minimum_coverage_by_file`.
90
+ def minimum_coverage_by_file_overrides
91
+ @minimum_coverage_by_file_overrides ||= {}
92
+ end
93
+
94
+ #
95
+ # Defines the minimum coverage per group required for the testsuite
96
+ # to pass. Default is 0% (disabled).
97
+ #
98
+ def minimum_coverage_by_group(coverage = nil)
99
+ return @minimum_coverage_by_group ||= {} unless coverage
100
+
101
+ SimpleCov::Deprecation.warn("`SimpleCov.minimum_coverage_by_group` is deprecated. " \
102
+ "Replace it with:\n#{per_group_coverage_replacement(coverage)}")
103
+ @minimum_coverage_by_group = coverage.dup.transform_values do |group_coverage|
104
+ group_coverage = {primary_coverage => group_coverage} if group_coverage.is_a?(Numeric)
105
+ raise_on_invalid_coverage(group_coverage, "minimum_coverage_by_group")
106
+ group_coverage
107
+ end
108
+ end
109
+
110
+ #
111
+ # Refuses any coverage drop. Coverage is only allowed to increase.
112
+ #
113
+ def refuse_coverage_drop(*criteria)
114
+ criteria = coverage_criteria if criteria.empty?
115
+ maximum_coverage_drop(criteria.to_h { |c| [c, 0] })
116
+ end
117
+
118
+ private
119
+
120
+ # Split a `minimum_coverage_by_file` argument into Symbol-keyed
121
+ # criterion defaults and String/Regexp-keyed per-path overrides;
122
+ # normalize Numeric override values to `{primary_coverage => N}`
123
+ # so downstream code only has one shape to handle.
124
+ def partition_per_file_thresholds(coverage)
125
+ coverage.each_key { |key| validate_per_file_key(key) }
126
+ pairs = coverage.partition { |key, _| key.is_a?(Symbol) }
127
+ # The assertions restate what the partition predicate guarantees:
128
+ # Symbol keys carry per-criterion Numeric defaults, the rest are paths.
129
+ defaults = pairs[0].to_h #: coverage_thresholds
130
+ raw = pairs[1].to_h #: Hash[String | Regexp, Numeric | coverage_thresholds]
131
+ overrides = raw.transform_values { |value| value.is_a?(Numeric) ? {primary_coverage => value} : value }
132
+ [defaults, overrides]
133
+ end
134
+
135
+ def validate_per_file_key(key)
136
+ return if key.is_a?(Symbol) || key.is_a?(String) || key.is_a?(Regexp)
137
+
138
+ raise SimpleCov::ConfigurationError,
139
+ "minimum_coverage_by_file keys must be Symbol (criterion), String, or Regexp; got #{key.inspect}"
140
+ end
141
+
142
+ def minimum_possible_coverage_exceeded(coverage_option)
143
+ warn "The coverage you set for #{coverage_option} is greater than 100%"
144
+ end
145
+
146
+ # Render the `coverage` configuration equivalent to a (deprecated)
147
+ # `minimum_coverage_by_file` argument so the deprecation warning can be
148
+ # copy-pasted verbatim into the user's config.
149
+ def per_file_coverage_replacement(defaults, overrides)
150
+ by_criterion = {} #: Hash[Symbol, Array[String]]
151
+ defaults.each { |criterion, percent| (by_criterion[criterion] ||= []) << "minimum_per_file #{percent}" }
152
+ overrides.each do |target, criteria|
153
+ criteria.each do |criterion, percent|
154
+ (by_criterion[criterion] ||= []) << "minimum_per_file #{percent}, only: #{target.inspect}"
155
+ end
156
+ end
157
+ render_coverage_blocks(by_criterion)
158
+ end
159
+
160
+ # Same, for a (deprecated) `minimum_coverage_by_group` argument.
161
+ def per_group_coverage_replacement(coverage)
162
+ by_criterion = {} #: Hash[Symbol, Array[String]]
163
+ coverage.each do |group_name, thresholds|
164
+ normalized = (thresholds.is_a?(Numeric) ? {primary_coverage => thresholds} : thresholds) #: coverage_thresholds
165
+ normalized.each do |criterion, percent|
166
+ (by_criterion[criterion] ||= []) << "minimum_per_group #{percent}, only: #{group_name.inspect}"
167
+ end
168
+ end
169
+ render_coverage_blocks(by_criterion)
170
+ end
171
+
172
+ def render_coverage_blocks(by_criterion)
173
+ by_criterion.map do |criterion, statements|
174
+ " coverage(#{criterion.inspect}) { #{statements.join('; ')} }"
175
+ end.join("\n")
176
+ end
177
+ end
178
+ end