simplecov 0.22.0 → 1.0.0

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 (115) 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 +91 -0
  11. data/lib/simplecov/cli/diff.rb +151 -0
  12. data/lib/simplecov/cli/dotfile.rb +100 -0
  13. data/lib/simplecov/cli/merge.rb +116 -0
  14. data/lib/simplecov/cli/open.rb +50 -0
  15. data/lib/simplecov/cli/report.rb +84 -0
  16. data/lib/simplecov/cli/run.rb +36 -0
  17. data/lib/simplecov/cli/serve.rb +139 -0
  18. data/lib/simplecov/cli/uncovered.rb +107 -0
  19. data/lib/simplecov/cli.rb +150 -0
  20. data/lib/simplecov/color.rb +74 -0
  21. data/lib/simplecov/combine/branches_combiner.rb +27 -5
  22. data/lib/simplecov/combine/files_combiner.rb +7 -1
  23. data/lib/simplecov/combine/lines_combiner.rb +19 -17
  24. data/lib/simplecov/combine/methods_combiner.rb +26 -0
  25. data/lib/simplecov/combine/results_combiner.rb +5 -4
  26. data/lib/simplecov/command_guesser.rb +46 -32
  27. data/lib/simplecov/configuration/coverage.rb +171 -0
  28. data/lib/simplecov/configuration/coverage_criteria.rb +156 -0
  29. data/lib/simplecov/configuration/filters.rb +197 -0
  30. data/lib/simplecov/configuration/formatting.rb +119 -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 +174 -0
  34. data/lib/simplecov/configuration.rb +91 -407
  35. data/lib/simplecov/coverage_statistics.rb +12 -9
  36. data/lib/simplecov/coverage_violations.rb +148 -0
  37. data/lib/simplecov/defaults.rb +27 -20
  38. data/lib/simplecov/deprecation.rb +45 -0
  39. data/lib/simplecov/directive.rb +162 -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 +3 -0
  47. data/lib/simplecov/exit_handling.rb +158 -0
  48. data/lib/simplecov/file_list.rb +61 -17
  49. data/lib/simplecov/filter.rb +69 -24
  50. data/lib/simplecov/formatter/base.rb +101 -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 +79 -0
  58. data/lib/simplecov/formatter/json_formatter/errors_formatter.rb +84 -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 +87 -0
  62. data/lib/simplecov/formatter/multi_formatter.rb +4 -5
  63. data/lib/simplecov/formatter/simple_formatter.rb +9 -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 +31 -13
  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 +70 -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 +7 -2
  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 +58 -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/method_collector.rb +55 -0
  104. data/lib/simplecov/static_coverage_extractor/visitor.rb +171 -0
  105. data/lib/simplecov/static_coverage_extractor.rb +110 -0
  106. data/lib/simplecov/useless_results_remover.rb +16 -7
  107. data/lib/simplecov/version.rb +1 -1
  108. data/lib/simplecov-html.rb +4 -0
  109. data/lib/simplecov.rb +156 -371
  110. data/lib/simplecov_json_formatter.rb +4 -0
  111. data/schemas/coverage-v1.0.schema.json +306 -0
  112. data/schemas/coverage.schema.json +306 -0
  113. metadata +90 -57
  114. data/CHANGELOG.md +0 -191
  115. data/lib/simplecov/default_formatter.rb +0 -20
@@ -0,0 +1,174 @@
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
+ defaults, raw = coverage.partition { |key, _| key.is_a?(Symbol) }.map(&:to_h)
127
+ overrides = raw.transform_values { |value| value.is_a?(Numeric) ? {primary_coverage => value} : value }
128
+ [defaults, overrides]
129
+ end
130
+
131
+ def validate_per_file_key(key)
132
+ return if key.is_a?(Symbol) || key.is_a?(String) || key.is_a?(Regexp)
133
+
134
+ raise SimpleCov::ConfigurationError,
135
+ "minimum_coverage_by_file keys must be Symbol (criterion), String, or Regexp; got #{key.inspect}"
136
+ end
137
+
138
+ def minimum_possible_coverage_exceeded(coverage_option)
139
+ warn "The coverage you set for #{coverage_option} is greater than 100%"
140
+ end
141
+
142
+ # Render the `coverage` configuration equivalent to a (deprecated)
143
+ # `minimum_coverage_by_file` argument so the deprecation warning can be
144
+ # copy-pasted verbatim into the user's config.
145
+ def per_file_coverage_replacement(defaults, overrides)
146
+ by_criterion = Hash.new { |hash, criterion| hash[criterion] = [] }
147
+ defaults.each { |criterion, percent| by_criterion[criterion] << "minimum_per_file #{percent}" }
148
+ overrides.each do |target, criteria|
149
+ criteria.each do |criterion, percent|
150
+ by_criterion[criterion] << "minimum_per_file #{percent}, only: #{target.inspect}"
151
+ end
152
+ end
153
+ render_coverage_blocks(by_criterion)
154
+ end
155
+
156
+ # Same, for a (deprecated) `minimum_coverage_by_group` argument.
157
+ def per_group_coverage_replacement(coverage)
158
+ by_criterion = Hash.new { |hash, criterion| hash[criterion] = [] }
159
+ coverage.each do |group_name, group_coverage|
160
+ group_coverage = {primary_coverage => group_coverage} if group_coverage.is_a?(Numeric)
161
+ group_coverage.each do |criterion, percent|
162
+ by_criterion[criterion] << "minimum_per_group #{percent}, only: #{group_name.inspect}"
163
+ end
164
+ end
165
+ render_coverage_blocks(by_criterion)
166
+ end
167
+
168
+ def render_coverage_blocks(by_criterion)
169
+ by_criterion.map do |criterion, statements|
170
+ " coverage(#{criterion.inspect}) { #{statements.join('; ')} }"
171
+ end.join("\n")
172
+ end
173
+ end
174
+ end