simplecov-patched 0.14.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.
- checksums.yaml +7 -0
- data/.gitignore +31 -0
- data/.rspec +3 -0
- data/.rubocop.yml +88 -0
- data/.travis.yml +29 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +435 -0
- data/CONTRIBUTING.md +48 -0
- data/Gemfile +38 -0
- data/MIT-LICENSE +20 -0
- data/README.md +646 -0
- data/Rakefile +41 -0
- data/cucumber.yml +13 -0
- data/doc/alternate-formatters.md +36 -0
- data/doc/commercial-services.md +20 -0
- data/doc/editor-integration.md +13 -0
- data/features/config_autoload.feature +46 -0
- data/features/config_command_name.feature +45 -0
- data/features/config_coverage_dir.feature +33 -0
- data/features/config_deactivate_merging.feature +42 -0
- data/features/config_formatters.feature +77 -0
- data/features/config_merge_timeout.feature +39 -0
- data/features/config_nocov_token.feature +79 -0
- data/features/config_profiles.feature +44 -0
- data/features/config_project_name.feature +27 -0
- data/features/config_styles.feature +121 -0
- data/features/config_tracked_files.feature +29 -0
- data/features/cucumber_basic.feature +29 -0
- data/features/maximum_coverage_drop.feature +89 -0
- data/features/merging_test_unit_and_rspec.feature +44 -0
- data/features/minimum_coverage.feature +59 -0
- data/features/refuse_coverage_drop.feature +95 -0
- data/features/rspec_basic.feature +32 -0
- data/features/rspec_fails_on_initialization.feature +14 -0
- data/features/rspec_groups_and_filters_basic.feature +29 -0
- data/features/rspec_groups_and_filters_complex.feature +37 -0
- data/features/rspec_groups_using_filter_class.feature +41 -0
- data/features/rspec_without_simplecov.feature +20 -0
- data/features/skipping_code_blocks_manually.feature +70 -0
- data/features/step_definitions/html_steps.rb +44 -0
- data/features/step_definitions/simplecov_steps.rb +68 -0
- data/features/step_definitions/transformers.rb +13 -0
- data/features/step_definitions/web_steps.rb +64 -0
- data/features/support/env.rb +50 -0
- data/features/test_unit_basic.feature +34 -0
- data/features/test_unit_groups_and_filters_basic.feature +29 -0
- data/features/test_unit_groups_and_filters_complex.feature +35 -0
- data/features/test_unit_groups_using_filter_class.feature +40 -0
- data/features/test_unit_without_simplecov.feature +20 -0
- data/features/unicode_compatiblity.feature +67 -0
- data/lib/simplecov.rb +189 -0
- data/lib/simplecov/command_guesser.rb +59 -0
- data/lib/simplecov/configuration.rb +307 -0
- data/lib/simplecov/defaults.rb +121 -0
- data/lib/simplecov/exit_codes.rb +8 -0
- data/lib/simplecov/file_list.rb +59 -0
- data/lib/simplecov/filter.rb +54 -0
- data/lib/simplecov/formatter.rb +8 -0
- data/lib/simplecov/formatter/multi_formatter.rb +32 -0
- data/lib/simplecov/formatter/simple_formatter.rb +23 -0
- data/lib/simplecov/jruby_fix.rb +42 -0
- data/lib/simplecov/last_run.rb +24 -0
- data/lib/simplecov/load_global_config.rb +6 -0
- data/lib/simplecov/no_defaults.rb +2 -0
- data/lib/simplecov/profiles.rb +31 -0
- data/lib/simplecov/railtie.rb +7 -0
- data/lib/simplecov/railties/tasks.rake +11 -0
- data/lib/simplecov/raw_coverage.rb +39 -0
- data/lib/simplecov/result.rb +86 -0
- data/lib/simplecov/result_merger.rb +95 -0
- data/lib/simplecov/source_file.rb +196 -0
- data/lib/simplecov/version.rb +25 -0
- data/spec/1_8_fallbacks_spec.rb +31 -0
- data/spec/command_guesser_spec.rb +48 -0
- data/spec/config_loader_spec.rb +14 -0
- data/spec/configuration_spec.rb +35 -0
- data/spec/deleted_source_spec.rb +12 -0
- data/spec/faked_project/Gemfile +6 -0
- data/spec/faked_project/Rakefile +8 -0
- data/spec/faked_project/cucumber.yml +13 -0
- data/spec/faked_project/features/step_definitions/my_steps.rb +22 -0
- data/spec/faked_project/features/support/env.rb +12 -0
- data/spec/faked_project/features/test_stuff.feature +6 -0
- data/spec/faked_project/lib/faked_project.rb +11 -0
- data/spec/faked_project/lib/faked_project/framework_specific.rb +18 -0
- data/spec/faked_project/lib/faked_project/meta_magic.rb +24 -0
- data/spec/faked_project/lib/faked_project/some_class.rb +28 -0
- data/spec/faked_project/lib/faked_project/untested_class.rb +11 -0
- data/spec/faked_project/spec/faked_spec.rb +11 -0
- data/spec/faked_project/spec/forking_spec.rb +8 -0
- data/spec/faked_project/spec/meta_magic_spec.rb +15 -0
- data/spec/faked_project/spec/some_class_spec.rb +13 -0
- data/spec/faked_project/spec/spec_helper.rb +11 -0
- data/spec/faked_project/test/faked_test.rb +11 -0
- data/spec/faked_project/test/meta_magic_test.rb +13 -0
- data/spec/faked_project/test/some_class_test.rb +15 -0
- data/spec/faked_project/test/test_helper.rb +12 -0
- data/spec/file_list_spec.rb +50 -0
- data/spec/filters_spec.rb +98 -0
- data/spec/fixtures/app/controllers/sample_controller.rb +10 -0
- data/spec/fixtures/app/models/user.rb +10 -0
- data/spec/fixtures/deleted_source_sample.rb +15 -0
- data/spec/fixtures/frameworks/rspec_bad.rb +9 -0
- data/spec/fixtures/frameworks/rspec_good.rb +9 -0
- data/spec/fixtures/frameworks/testunit_bad.rb +9 -0
- data/spec/fixtures/frameworks/testunit_good.rb +9 -0
- data/spec/fixtures/iso-8859.rb +3 -0
- data/spec/fixtures/never.rb +2 -0
- data/spec/fixtures/resultset1.rb +4 -0
- data/spec/fixtures/resultset2.rb +4 -0
- data/spec/fixtures/sample.rb +16 -0
- data/spec/fixtures/skipped.rb +4 -0
- data/spec/fixtures/skipped_and_executed.rb +8 -0
- data/spec/fixtures/utf-8.rb +3 -0
- data/spec/helper.rb +26 -0
- data/spec/last_run_spec.rb +48 -0
- data/spec/multi_formatter_spec.rb +20 -0
- data/spec/raw_coverage_spec.rb +92 -0
- data/spec/result_merger_spec.rb +96 -0
- data/spec/result_spec.rb +209 -0
- data/spec/return_codes_spec.rb +34 -0
- data/spec/simplecov_spec.rb +110 -0
- data/spec/source_file_line_spec.rb +155 -0
- data/spec/source_file_spec.rb +141 -0
- data/spec/support/fail_rspec_on_ruby_warning.rb +75 -0
- metadata +320 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Helper that tries to find out what test suite is running (for SimpleCov.command_name)
|
|
3
|
+
#
|
|
4
|
+
module SimpleCov
|
|
5
|
+
module CommandGuesser
|
|
6
|
+
class << self
|
|
7
|
+
# Storage for the original command line call that invoked the test suite.
|
|
8
|
+
# This has got to be stored as early as possible because i.e. rake and test/unit 2
|
|
9
|
+
# have a habit of tampering with ARGV, which makes i.e. the automatic distinction
|
|
10
|
+
# between rails unit/functional/integration tests impossible without this cached
|
|
11
|
+
# item.
|
|
12
|
+
attr_accessor :original_run_command
|
|
13
|
+
|
|
14
|
+
def guess
|
|
15
|
+
from_env || from_command_line_options || from_defined_constants
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def from_env
|
|
21
|
+
# If being run from inside parallel_tests set the command name according to the process number
|
|
22
|
+
return unless ENV["PARALLEL_TEST_GROUPS"] && ENV["TEST_ENV_NUMBER"]
|
|
23
|
+
number = ENV["TEST_ENV_NUMBER"]
|
|
24
|
+
number = "1" if number.empty?
|
|
25
|
+
"(#{number}/#{ENV['PARALLEL_TEST_GROUPS']})"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def from_command_line_options
|
|
29
|
+
case original_run_command
|
|
30
|
+
when /test\/functional\//, /test\/\{.*functional.*\}\//
|
|
31
|
+
"Functional Tests"
|
|
32
|
+
when /test\/integration\//
|
|
33
|
+
"Integration Tests"
|
|
34
|
+
when /test\//
|
|
35
|
+
"Unit Tests"
|
|
36
|
+
when /spec/
|
|
37
|
+
"RSpec"
|
|
38
|
+
when /cucumber/, /features/
|
|
39
|
+
"Cucumber Features"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def from_defined_constants
|
|
44
|
+
# If the command regexps fail, let's try checking defined constants.
|
|
45
|
+
if defined?(RSpec)
|
|
46
|
+
"RSpec"
|
|
47
|
+
elsif defined?(Test::Unit)
|
|
48
|
+
"Unit Tests"
|
|
49
|
+
elsif defined?(MiniTest)
|
|
50
|
+
"MiniTest"
|
|
51
|
+
else
|
|
52
|
+
# TODO: Provide link to docs/wiki article
|
|
53
|
+
warn "SimpleCov failed to recognize the test framework and/or suite used. Please specify manually using SimpleCov.command_name 'Unit Tests'."
|
|
54
|
+
"Unknown Test Framework"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
require "fileutils"
|
|
2
|
+
require "docile"
|
|
3
|
+
require "simplecov/formatter/multi_formatter"
|
|
4
|
+
#
|
|
5
|
+
# Bundles the configuration options used for SimpleCov. All methods
|
|
6
|
+
# defined here are usable from SimpleCov directly. Please check out
|
|
7
|
+
# SimpleCov documentation for further info.
|
|
8
|
+
#
|
|
9
|
+
module SimpleCov
|
|
10
|
+
module Configuration # rubocop:disable ModuleLength
|
|
11
|
+
attr_writer :filters, :groups, :formatter
|
|
12
|
+
|
|
13
|
+
#
|
|
14
|
+
# The root for the project. This defaults to the
|
|
15
|
+
# current working directory.
|
|
16
|
+
#
|
|
17
|
+
# Configure with SimpleCov.root('/my/project/path')
|
|
18
|
+
#
|
|
19
|
+
def root(root = nil)
|
|
20
|
+
return @root if defined?(@root) && root.nil?
|
|
21
|
+
@root = File.expand_path(root || Dir.getwd)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# The name of the output and cache directory. Defaults to 'coverage'
|
|
26
|
+
#
|
|
27
|
+
# Configure with SimpleCov.coverage_dir('cov')
|
|
28
|
+
#
|
|
29
|
+
def coverage_dir(dir = nil)
|
|
30
|
+
return @coverage_dir if defined?(@coverage_dir) && dir.nil?
|
|
31
|
+
@coverage_path = nil # invalidate cache
|
|
32
|
+
@coverage_dir = (dir || "coverage")
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
# Returns the full path to the output directory using SimpleCov.root
|
|
37
|
+
# and SimpleCov.coverage_dir, so you can adjust this by configuring those
|
|
38
|
+
# values. Will create the directory if it's missing
|
|
39
|
+
#
|
|
40
|
+
def coverage_path
|
|
41
|
+
@coverage_path ||= begin
|
|
42
|
+
coverage_path = File.expand_path(coverage_dir, root)
|
|
43
|
+
FileUtils.mkdir_p coverage_path
|
|
44
|
+
coverage_path
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# Coverage results will always include files matched by this glob, whether
|
|
50
|
+
# or not they were explicitly required. Without this, un-required files
|
|
51
|
+
# will not be present in the final report.
|
|
52
|
+
#
|
|
53
|
+
def track_files(glob)
|
|
54
|
+
@tracked_files = glob
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
#
|
|
58
|
+
# Returns the glob that will be used to include files that were not
|
|
59
|
+
# explicitly required.
|
|
60
|
+
#
|
|
61
|
+
def tracked_files
|
|
62
|
+
@tracked_files if defined?(@tracked_files)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# Returns the list of configured filters. Add filters using SimpleCov.add_filter.
|
|
67
|
+
#
|
|
68
|
+
def filters
|
|
69
|
+
@filters ||= []
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# The name of the command (a.k.a. Test Suite) currently running. Used for result
|
|
73
|
+
# merging and caching. It first tries to make a guess based upon the command line
|
|
74
|
+
# arguments the current test suite is running on and should automatically detect
|
|
75
|
+
# unit tests, functional tests, integration tests, rpsec and cucumber and label
|
|
76
|
+
# them properly. If it fails to recognize the current command, the command name
|
|
77
|
+
# is set to the shell command that the current suite is running on.
|
|
78
|
+
#
|
|
79
|
+
# You can specify it manually with SimpleCov.command_name("test:units") - please
|
|
80
|
+
# also check out the corresponding section in README.rdoc
|
|
81
|
+
def command_name(name = nil)
|
|
82
|
+
@name = name unless name.nil?
|
|
83
|
+
@name ||= SimpleCov::CommandGuesser.guess
|
|
84
|
+
@name
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
#
|
|
88
|
+
# Gets or sets the configured formatter.
|
|
89
|
+
#
|
|
90
|
+
# Configure with: SimpleCov.formatter(SimpleCov::Formatter::SimpleFormatter)
|
|
91
|
+
#
|
|
92
|
+
def formatter(formatter = nil)
|
|
93
|
+
return @formatter if defined?(@formatter) && formatter.nil?
|
|
94
|
+
@formatter = formatter
|
|
95
|
+
raise "No formatter configured. Please specify a formatter using SimpleCov.formatter = SimpleCov::Formatter::SimpleFormatter" unless @formatter
|
|
96
|
+
@formatter
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
#
|
|
100
|
+
# Sets the configured formatters.
|
|
101
|
+
#
|
|
102
|
+
def formatters=(formatters)
|
|
103
|
+
@formatter = SimpleCov::Formatter::MultiFormatter.new(formatters)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
#
|
|
107
|
+
# Gets the configured formatters.
|
|
108
|
+
#
|
|
109
|
+
def formatters
|
|
110
|
+
if @formatter.is_a?(SimpleCov::Formatter::MultiFormatter)
|
|
111
|
+
@formatter.formatters
|
|
112
|
+
else
|
|
113
|
+
Array(formatter)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# Certain code blocks (i.e. Ruby-implementation specific code) can be excluded from
|
|
119
|
+
# the coverage metrics by wrapping it inside # :nocov: comment blocks. The nocov token
|
|
120
|
+
# can be configured to be any other string using this.
|
|
121
|
+
#
|
|
122
|
+
# Configure with SimpleCov.nocov_token('skip') or it's alias SimpleCov.skip_token('skip')
|
|
123
|
+
#
|
|
124
|
+
def nocov_token(nocov_token = nil)
|
|
125
|
+
return @nocov_token if defined?(@nocov_token) && nocov_token.nil?
|
|
126
|
+
@nocov_token = (nocov_token || "nocov")
|
|
127
|
+
end
|
|
128
|
+
alias skip_token nocov_token
|
|
129
|
+
|
|
130
|
+
#
|
|
131
|
+
# Returns the configured groups. Add groups using SimpleCov.add_group
|
|
132
|
+
#
|
|
133
|
+
def groups
|
|
134
|
+
@groups ||= {}
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
#
|
|
138
|
+
# Returns the hash of available profiles
|
|
139
|
+
#
|
|
140
|
+
def profiles
|
|
141
|
+
@profiles ||= SimpleCov::Profiles.new
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def adapters
|
|
145
|
+
warn "#{Kernel.caller.first}: [DEPRECATION] #adapters is deprecated. Use #profiles instead."
|
|
146
|
+
profiles
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
#
|
|
150
|
+
# Allows you to configure simplecov in a block instead of prepending SimpleCov to all config methods
|
|
151
|
+
# you're calling.
|
|
152
|
+
#
|
|
153
|
+
# SimpleCov.configure do
|
|
154
|
+
# add_filter 'foobar'
|
|
155
|
+
# end
|
|
156
|
+
#
|
|
157
|
+
# This is equivalent to SimpleCov.add_filter 'foobar' and thus makes it easier to set a bunch of configure
|
|
158
|
+
# options at once.
|
|
159
|
+
#
|
|
160
|
+
def configure(&block)
|
|
161
|
+
return false unless SimpleCov.usable?
|
|
162
|
+
Docile.dsl_eval(self, &block)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
#
|
|
166
|
+
# Gets or sets the behavior to process coverage results.
|
|
167
|
+
#
|
|
168
|
+
# By default, it will call SimpleCov.result.format!
|
|
169
|
+
#
|
|
170
|
+
# Configure with:
|
|
171
|
+
#
|
|
172
|
+
# SimpleCov.at_exit do
|
|
173
|
+
# puts "Coverage done"
|
|
174
|
+
# SimpleCov.result.format!
|
|
175
|
+
# end
|
|
176
|
+
#
|
|
177
|
+
def at_exit(&block)
|
|
178
|
+
return proc {} unless running || block_given?
|
|
179
|
+
@at_exit = block if block_given?
|
|
180
|
+
@at_exit ||= proc { SimpleCov.result.format! }
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
#
|
|
184
|
+
# Returns the project name - currently assuming the last dirname in
|
|
185
|
+
# the SimpleCov.root is this.
|
|
186
|
+
#
|
|
187
|
+
def project_name(new_name = nil)
|
|
188
|
+
return @project_name if defined?(@project_name) && @project_name && new_name.nil?
|
|
189
|
+
@project_name = new_name if new_name.is_a?(String)
|
|
190
|
+
@project_name ||= File.basename(root.split("/").last).capitalize.tr("_", " ")
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
#
|
|
194
|
+
# Defines whether to use result merging so all your test suites (test:units, test:functionals, cucumber, ...)
|
|
195
|
+
# are joined and combined into a single coverage report
|
|
196
|
+
#
|
|
197
|
+
def use_merging(use = nil)
|
|
198
|
+
@use_merging = use unless use.nil?
|
|
199
|
+
@use_merging = true unless defined?(@use_merging) && @use_merging == false
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
#
|
|
203
|
+
# Defines the maximum age (in seconds) of a resultset to still be included in merged results.
|
|
204
|
+
# i.e. If you run cucumber features, then later rake test, if the stored cucumber resultset is
|
|
205
|
+
# more seconds ago than specified here, it won't be taken into account when merging (and is also
|
|
206
|
+
# purged from the resultset cache)
|
|
207
|
+
#
|
|
208
|
+
# Of course, this only applies when merging is active (e.g. SimpleCov.use_merging is not false!)
|
|
209
|
+
#
|
|
210
|
+
# Default is 600 seconds (10 minutes)
|
|
211
|
+
#
|
|
212
|
+
# Configure with SimpleCov.merge_timeout(3600) # 1hr
|
|
213
|
+
#
|
|
214
|
+
def merge_timeout(seconds = nil)
|
|
215
|
+
@merge_timeout = seconds if seconds.is_a?(Integer)
|
|
216
|
+
@merge_timeout ||= 600
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
#
|
|
220
|
+
# Defines the minimum overall coverage required for the testsuite to pass.
|
|
221
|
+
# SimpleCov will return non-zero if the current coverage is below this threshold.
|
|
222
|
+
#
|
|
223
|
+
# Default is 0% (disabled)
|
|
224
|
+
#
|
|
225
|
+
def minimum_coverage(coverage = nil)
|
|
226
|
+
@minimum_coverage ||= (coverage || 0).to_f.round(2)
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
#
|
|
230
|
+
# Defines the maximum coverage drop at once allowed for the testsuite to pass.
|
|
231
|
+
# SimpleCov will return non-zero if the coverage decreases by more than this threshold.
|
|
232
|
+
#
|
|
233
|
+
# Default is 100% (disabled)
|
|
234
|
+
#
|
|
235
|
+
def maximum_coverage_drop(coverage_drop = nil)
|
|
236
|
+
@maximum_coverage_drop ||= (coverage_drop || 100).to_f.round(2)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
#
|
|
240
|
+
# Defines the minimum coverage per file required for the testsuite to pass.
|
|
241
|
+
# SimpleCov will return non-zero if the current coverage of the least covered file
|
|
242
|
+
# is below this threshold.
|
|
243
|
+
#
|
|
244
|
+
# Default is 0% (disabled)
|
|
245
|
+
#
|
|
246
|
+
def minimum_coverage_by_file(coverage = nil)
|
|
247
|
+
@minimum_coverage_by_file ||= (coverage || 0).to_f.round(2)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
#
|
|
251
|
+
# Refuses any coverage drop. That is, coverage is only allowed to increase.
|
|
252
|
+
# SimpleCov will return non-zero if the coverage decreases.
|
|
253
|
+
#
|
|
254
|
+
def refuse_coverage_drop
|
|
255
|
+
maximum_coverage_drop 0
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
#
|
|
259
|
+
# Add a filter to the processing chain.
|
|
260
|
+
# There are four ways to define a filter:
|
|
261
|
+
#
|
|
262
|
+
# * as a String that will then be matched against all source files' file paths,
|
|
263
|
+
# SimpleCov.add_filter 'app/models' # will reject all your models
|
|
264
|
+
# * as a block which will be passed the source file in question and should either
|
|
265
|
+
# return a true or false value, depending on whether the file should be removed
|
|
266
|
+
# SimpleCov.add_filter do |src_file|
|
|
267
|
+
# File.basename(src_file.filename) == 'environment.rb'
|
|
268
|
+
# end # Will exclude environment.rb files from the results
|
|
269
|
+
# * as an array of strings that are matched against all sorce files' file
|
|
270
|
+
# paths and then ignored (basically string filter multiple times)
|
|
271
|
+
# SimpleCov.add_filter ['app/models', 'app/helpers'] # ignores both dirs
|
|
272
|
+
# * as an instance of a subclass of SimpleCov::Filter. See the documentation there
|
|
273
|
+
# on how to define your own filter classes
|
|
274
|
+
#
|
|
275
|
+
def add_filter(filter_argument = nil, &filter_proc)
|
|
276
|
+
filters << parse_filter(filter_argument, &filter_proc)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
#
|
|
280
|
+
# Define a group for files. Works similar to add_filter, only that the first
|
|
281
|
+
# argument is the desired group name and files PASSING the filter end up in the group
|
|
282
|
+
# (while filters exclude when the filter is applicable).
|
|
283
|
+
#
|
|
284
|
+
def add_group(group_name, filter_argument = nil, &filter_proc)
|
|
285
|
+
groups[group_name] = parse_filter(filter_argument, &filter_proc)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
private
|
|
289
|
+
|
|
290
|
+
#
|
|
291
|
+
# The actual filter processor. Not meant for direct use
|
|
292
|
+
#
|
|
293
|
+
def parse_filter(filter_argument = nil, &filter_proc)
|
|
294
|
+
if filter_argument.is_a?(SimpleCov::Filter)
|
|
295
|
+
filter_argument
|
|
296
|
+
elsif filter_argument.is_a?(String)
|
|
297
|
+
SimpleCov::StringFilter.new(filter_argument)
|
|
298
|
+
elsif filter_proc
|
|
299
|
+
SimpleCov::BlockFilter.new(filter_proc)
|
|
300
|
+
elsif filter_argument.is_a?(Array)
|
|
301
|
+
SimpleCov::ArrayFilter.new(filter_argument)
|
|
302
|
+
else
|
|
303
|
+
raise ArgumentError, "Please specify either a string or a block to filter with"
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Load default formatter gem
|
|
2
|
+
require "simplecov-html"
|
|
3
|
+
require "pathname"
|
|
4
|
+
|
|
5
|
+
SimpleCov.profiles.define "root_filter" do
|
|
6
|
+
# Exclude all files outside of simplecov root
|
|
7
|
+
root_filter = nil
|
|
8
|
+
add_filter do |src|
|
|
9
|
+
root_filter ||= /\A#{Regexp.escape(SimpleCov.root)}/io
|
|
10
|
+
src.filename !~ root_filter
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
SimpleCov.profiles.define "test_frameworks" do
|
|
15
|
+
add_filter "/test/"
|
|
16
|
+
add_filter "/features/"
|
|
17
|
+
add_filter "/spec/"
|
|
18
|
+
add_filter "/autotest/"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
SimpleCov.profiles.define "bundler_filter" do
|
|
22
|
+
add_filter "/vendor/bundle/"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
SimpleCov.profiles.define "rails" do
|
|
26
|
+
load_profile "test_frameworks"
|
|
27
|
+
|
|
28
|
+
add_filter "/config/"
|
|
29
|
+
add_filter "/db/"
|
|
30
|
+
|
|
31
|
+
add_group "Controllers", "app/controllers"
|
|
32
|
+
add_group "Channels", "app/channels" if defined?(ActionCable)
|
|
33
|
+
add_group "Models", "app/models"
|
|
34
|
+
add_group "Mailers", "app/mailers"
|
|
35
|
+
add_group "Helpers", "app/helpers"
|
|
36
|
+
add_group "Jobs", %w[app/jobs app/workers]
|
|
37
|
+
add_group "Libraries", "lib"
|
|
38
|
+
|
|
39
|
+
track_files "{app,lib}/**/*.rb"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Default configuration
|
|
43
|
+
SimpleCov.configure do
|
|
44
|
+
formatter SimpleCov::Formatter::HTMLFormatter
|
|
45
|
+
load_profile "bundler_filter"
|
|
46
|
+
# Exclude files outside of SimpleCov.root
|
|
47
|
+
load_profile "root_filter"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Gotta stash this a-s-a-p, see the CommandGuesser class and i.e. #110 for further info
|
|
51
|
+
SimpleCov::CommandGuesser.original_run_command = "#{$PROGRAM_NAME} #{ARGV.join(' ')}"
|
|
52
|
+
|
|
53
|
+
at_exit do # rubocop:disable Metrics/BlockLength
|
|
54
|
+
# If we are in a different process than called start, don't interfere.
|
|
55
|
+
next if SimpleCov.pid != Process.pid
|
|
56
|
+
|
|
57
|
+
@exit_status = if $! # was an exception thrown?
|
|
58
|
+
# if it was a SystemExit, use the accompanying status
|
|
59
|
+
# otherwise set a non-zero status representing termination by
|
|
60
|
+
# some other exception (see github issue 41)
|
|
61
|
+
$!.is_a?(SystemExit) ? $!.status : SimpleCov::ExitCodes::EXCEPTION
|
|
62
|
+
else
|
|
63
|
+
# Store the exit status of the test run since it goes away
|
|
64
|
+
# after calling the at_exit proc...
|
|
65
|
+
SimpleCov::ExitCodes::SUCCESS
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
SimpleCov.at_exit.call
|
|
69
|
+
|
|
70
|
+
if SimpleCov.result? # Result has been computed
|
|
71
|
+
covered_percent = SimpleCov.result.covered_percent.round(2)
|
|
72
|
+
covered_percentages = SimpleCov.result.covered_percentages.map { |p| p.round(2) }
|
|
73
|
+
|
|
74
|
+
if @exit_status == SimpleCov::ExitCodes::SUCCESS # No other errors
|
|
75
|
+
if covered_percent < SimpleCov.minimum_coverage # rubocop:disable Metrics/BlockNesting
|
|
76
|
+
$stderr.printf("Coverage (%.2f%%) is below the expected minimum coverage (%.2f%%).\n", covered_percent, SimpleCov.minimum_coverage)
|
|
77
|
+
@exit_status = SimpleCov::ExitCodes::MINIMUM_COVERAGE
|
|
78
|
+
elsif covered_percentages.any? { |p| p < SimpleCov.minimum_coverage_by_file } # rubocop:disable Metrics/BlockNesting
|
|
79
|
+
$stderr.printf("File (%s) is only (%.2f%%) covered. This is below the expected minimum coverage per file of (%.2f%%).\n", SimpleCov.result.least_covered_file, covered_percentages.min, SimpleCov.minimum_coverage_by_file)
|
|
80
|
+
@exit_status = SimpleCov::ExitCodes::MINIMUM_COVERAGE
|
|
81
|
+
elsif (last_run = SimpleCov::LastRun.read) # rubocop:disable Metrics/BlockNesting
|
|
82
|
+
coverage_diff = last_run["result"]["covered_percent"] - covered_percent
|
|
83
|
+
if coverage_diff > SimpleCov.maximum_coverage_drop # rubocop:disable Metrics/BlockNesting
|
|
84
|
+
$stderr.printf("Coverage has dropped by %.2f%% since the last time (maximum allowed: %.2f%%).\n", coverage_diff, SimpleCov.maximum_coverage_drop)
|
|
85
|
+
@exit_status = SimpleCov::ExitCodes::MAXIMUM_COVERAGE_DROP
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Don't overwrite last_run file if refuse_coverage_drop option is enabled and the coverage has dropped
|
|
91
|
+
unless @exit_status == SimpleCov::ExitCodes::MAXIMUM_COVERAGE_DROP
|
|
92
|
+
SimpleCov::LastRun.write(:result => {:covered_percent => covered_percent})
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Force exit with stored status (see github issue #5)
|
|
97
|
+
# unless it's nil or 0 (see github issue #281)
|
|
98
|
+
Kernel.exit @exit_status if @exit_status && @exit_status > 0
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Autoload config from ~/.simplecov if present
|
|
102
|
+
require "simplecov/load_global_config"
|
|
103
|
+
|
|
104
|
+
# Autoload config from .simplecov if present
|
|
105
|
+
# Recurse upwards until we find .simplecov or reach the root directory
|
|
106
|
+
|
|
107
|
+
config_path = Pathname.new(SimpleCov.root)
|
|
108
|
+
loop do
|
|
109
|
+
filename = config_path.join(".simplecov")
|
|
110
|
+
if filename.exist?
|
|
111
|
+
begin
|
|
112
|
+
load filename
|
|
113
|
+
rescue LoadError, StandardError
|
|
114
|
+
$stderr.puts "Warning: Error occurred while trying to load #{filename}. " \
|
|
115
|
+
"Error message: #{$!.message}"
|
|
116
|
+
end
|
|
117
|
+
break
|
|
118
|
+
end
|
|
119
|
+
config_path, = config_path.split
|
|
120
|
+
break if config_path.root?
|
|
121
|
+
end
|