rubocop-minitest 0.39.1 → 0.40.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.
- checksums.yaml +4 -4
- data/README.md +90 -0
- data/lib/rubocop/cop/minitest/non_executable_test_method.rb +6 -1
- data/lib/rubocop/minitest/assert_offense.rb +182 -16
- data/lib/rubocop/minitest/support.rb +1 -0
- data/lib/rubocop/minitest/version.rb +1 -1
- data/lib/rubocop/test_case.rb +29 -0
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eda17cda5caf90c2cf74b9f760a0ba38d1cf1c9e5d73c16c450dc4b905bb0105
|
|
4
|
+
data.tar.gz: a623715c3491d9eaa408842b98f790cc95c761d75fe5c42e0a9bb8b32c0730bf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ea451f9315708de691d4fec8a1190f7c3ad20c1f601ea784f05d20289d43cbec4f6471ef257ed0ef63341c20c8abac9f990db749a7faa1b12af6c5fe6725904d
|
|
7
|
+
data.tar.gz: e8404442a84c387f85c38d270a8312d2f0e0b37105cabf9bd0b5a25d3ac9bf3d48267659b25c4432f7ef335315f1fc3df585c1223ec9acc16c35e541fdc858fb
|
data/README.md
CHANGED
|
@@ -78,6 +78,96 @@ Minitest/AssertNil:
|
|
|
78
78
|
- test/my_file_to_ignore_test.rb
|
|
79
79
|
```
|
|
80
80
|
|
|
81
|
+
## Testing your own cops
|
|
82
|
+
|
|
83
|
+
This gem provides `RuboCop::TestCase`, a base test case class for testing custom cops with Minitest.
|
|
84
|
+
Require `rubocop/minitest/support` in your test helper, then inherit from `RuboCop::TestCase` to get
|
|
85
|
+
the `assert_offense`, `assert_correction`, `assert_no_corrections`, and `assert_no_offenses` assertions:
|
|
86
|
+
|
|
87
|
+
```ruby
|
|
88
|
+
require 'rubocop/minitest/support'
|
|
89
|
+
|
|
90
|
+
module CustomCops
|
|
91
|
+
class MyCopTest < RuboCop::TestCase
|
|
92
|
+
def test_registers_offense
|
|
93
|
+
assert_offense(<<~RUBY)
|
|
94
|
+
bad_method
|
|
95
|
+
^^^^^^^^^^ Use `good_method` instead of `bad_method`.
|
|
96
|
+
RUBY
|
|
97
|
+
|
|
98
|
+
assert_correction(<<~RUBY)
|
|
99
|
+
good_method
|
|
100
|
+
RUBY
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def test_does_not_register_offense
|
|
104
|
+
assert_no_offenses(<<~RUBY)
|
|
105
|
+
good_method
|
|
106
|
+
RUBY
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The cop under test is derived from the test class name: `CustomCops::MyCopTest` resolves
|
|
113
|
+
`CustomCops::MyCop`, then `RuboCop::Cop::Minitest::MyCop`. Define a `cop_class` method in
|
|
114
|
+
the test class to specify the cop explicitly:
|
|
115
|
+
|
|
116
|
+
```ruby
|
|
117
|
+
class MyCopTest < RuboCop::TestCase
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
def cop_class
|
|
121
|
+
CustomCops::MyCop
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The configuration for the cop under test and the target Ruby version can be specified
|
|
127
|
+
by overriding `cop_config`, `other_cops`, or `target_ruby_version` in the test class:
|
|
128
|
+
|
|
129
|
+
```ruby
|
|
130
|
+
class MyCopTest < RuboCop::TestCase
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
def cop_config
|
|
134
|
+
{ 'Max' => 1 }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def target_ruby_version
|
|
138
|
+
3.0
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
To change them for a single test, assign them in the test method. This makes it
|
|
144
|
+
possible for tests targeting different Ruby versions to live in the same test class:
|
|
145
|
+
|
|
146
|
+
```ruby
|
|
147
|
+
class MyCopTest < RuboCop::TestCase
|
|
148
|
+
def test_registers_offense_on_ruby31
|
|
149
|
+
self.target_ruby_version = 3.1
|
|
150
|
+
|
|
151
|
+
assert_offense(<<~RUBY)
|
|
152
|
+
bad_method
|
|
153
|
+
^^^^^^^^^^ Use `good_method` instead of `bad_method`.
|
|
154
|
+
RUBY
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def test_does_not_register_offense_on_ruby30
|
|
158
|
+
self.target_ruby_version = 3.0
|
|
159
|
+
|
|
160
|
+
assert_no_offenses(<<~RUBY)
|
|
161
|
+
bad_method
|
|
162
|
+
RUBY
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
The default configuration of extensions registered as [lint_roller](https://github.com/standardrb/lint_roller) plugins
|
|
168
|
+
is applied automatically. For other extensions, call `RuboCop::ConfigLoader.inject_defaults!('path/to/default.yml')`
|
|
169
|
+
in your test helper.
|
|
170
|
+
|
|
81
171
|
## Documentation
|
|
82
172
|
|
|
83
173
|
You can read a lot more about RuboCop Minitest in its [official docs](https://docs.rubocop.org/rubocop-minitest/).
|
|
@@ -31,7 +31,8 @@ module RuboCop
|
|
|
31
31
|
|
|
32
32
|
def on_def(node)
|
|
33
33
|
return if !test_method?(node) || !use_test_class?
|
|
34
|
-
return if
|
|
34
|
+
return if inside_test_class?(node)
|
|
35
|
+
return if (node.left_siblings + node.right_siblings).none? { |sibling| possible_test_class?(sibling) }
|
|
35
36
|
|
|
36
37
|
add_offense(node)
|
|
37
38
|
end
|
|
@@ -44,6 +45,10 @@ module RuboCop
|
|
|
44
45
|
root_node.each_descendant(:class).any? { |class_node| test_class?(class_node) }
|
|
45
46
|
end
|
|
46
47
|
|
|
48
|
+
def inside_test_class?(node)
|
|
49
|
+
node.each_ancestor(:class).any? { |class_node| test_class?(class_node) }
|
|
50
|
+
end
|
|
51
|
+
|
|
47
52
|
def possible_test_class?(node)
|
|
48
53
|
node.is_a?(AST::ClassNode) && test_class?(node) && node.parent_class.source.include?('Test')
|
|
49
54
|
end
|
|
@@ -71,17 +71,138 @@ module RuboCop
|
|
|
71
71
|
#
|
|
72
72
|
# assert_no_corrections
|
|
73
73
|
#
|
|
74
|
+
# The cop under test is derived from the test class name: `FooTest` resolves
|
|
75
|
+
# the `Foo` constant in the test class's namespace, then `RuboCop::Cop::Minitest::Foo`.
|
|
76
|
+
# Define a `cop_class` method in the test class to specify the cop explicitly:
|
|
77
|
+
#
|
|
78
|
+
# class AssertNilTest < RuboCop::TestCase
|
|
79
|
+
# private
|
|
80
|
+
#
|
|
81
|
+
# def cop_class
|
|
82
|
+
# RuboCop::Cop::Minitest::AssertNil
|
|
83
|
+
# end
|
|
84
|
+
# end
|
|
85
|
+
#
|
|
86
|
+
# The configuration for the cop under test and the target Ruby version can be specified
|
|
87
|
+
# by overriding `cop_config`, `other_cops`, or `target_ruby_version` in the test class:
|
|
88
|
+
#
|
|
89
|
+
# @example `cop_config` and `target_ruby_version`
|
|
90
|
+
#
|
|
91
|
+
# class MultipleAssertionsTest < RuboCop::TestCase
|
|
92
|
+
# private
|
|
93
|
+
#
|
|
94
|
+
# def cop_config
|
|
95
|
+
# { 'Max' => 1 }
|
|
96
|
+
# end
|
|
97
|
+
#
|
|
98
|
+
# def target_ruby_version
|
|
99
|
+
# 3.0
|
|
100
|
+
# end
|
|
101
|
+
# end
|
|
102
|
+
#
|
|
103
|
+
# To change them for a single test, assign them in the test method.
|
|
104
|
+
# This makes it possible for tests targeting different Ruby versions to live in the same test class:
|
|
105
|
+
#
|
|
106
|
+
# @example assigning `target_ruby_version` per test
|
|
107
|
+
#
|
|
108
|
+
# class MyCopTest < RuboCop::TestCase
|
|
109
|
+
# def test_registers_offense_on_ruby31
|
|
110
|
+
# self.target_ruby_version = 3.1
|
|
111
|
+
#
|
|
112
|
+
# assert_offense(<<~RUBY)
|
|
113
|
+
# ...
|
|
114
|
+
# RUBY
|
|
115
|
+
# end
|
|
116
|
+
#
|
|
117
|
+
# def test_does_not_register_offense_on_ruby30
|
|
118
|
+
# self.target_ruby_version = 3.0
|
|
119
|
+
#
|
|
120
|
+
# assert_no_offenses(<<~RUBY)
|
|
121
|
+
# ...
|
|
122
|
+
# RUBY
|
|
123
|
+
# end
|
|
124
|
+
# end
|
|
125
|
+
#
|
|
74
126
|
# rubocop:disable Metrics/ModuleLength
|
|
75
127
|
module AssertOffense
|
|
128
|
+
PLUGIN_INTEGRATION_MUTEX = Mutex.new
|
|
129
|
+
private_constant :PLUGIN_INTEGRATION_MUTEX
|
|
130
|
+
|
|
131
|
+
# Initialized here so that reading it under `ruby -w` does not warn before the first assignment.
|
|
132
|
+
@integrated_plugins = nil
|
|
133
|
+
|
|
134
|
+
class << self
|
|
135
|
+
# Makes the default configuration of extensions registered as lint_roller plugins visible
|
|
136
|
+
# through `RuboCop::ConfigLoader.default_configuration`.
|
|
137
|
+
# Guarded by a mutex so that parallel test threads reaching their first assertion at the same time
|
|
138
|
+
# do not integrate plugins twice or race on the lazy initialization of the default configuration.
|
|
139
|
+
def integrate_plugins!
|
|
140
|
+
PLUGIN_INTEGRATION_MUTEX.synchronize do
|
|
141
|
+
next if @integrated_plugins
|
|
142
|
+
|
|
143
|
+
plugins = Gem.loaded_specs.filter_map do |feature_name, feature_specification|
|
|
144
|
+
feature_name if feature_specification.metadata['default_lint_roller_plugin']
|
|
145
|
+
end
|
|
146
|
+
RuboCop::Plugin.integrate_plugins(RuboCop::Config.new, plugins)
|
|
147
|
+
|
|
148
|
+
@integrated_plugins = true
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
76
153
|
private
|
|
77
154
|
|
|
78
155
|
def cop
|
|
79
156
|
@cop ||= begin
|
|
80
|
-
|
|
81
|
-
|
|
157
|
+
unless cop_class
|
|
158
|
+
raise "Could not determine the cop class under test from `#{self.class}`. " \
|
|
159
|
+
'The cop class is derived from the test class name (e.g. `FooTest` resolves `Foo` ' \
|
|
160
|
+
"in the test class's namespace, then `RuboCop::Cop::Minitest::Foo`). " \
|
|
161
|
+
'Define a `cop_class` method in your test class to specify it explicitly.'
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
cop_class.new(configuration)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def cop_class
|
|
169
|
+
@cop_class ||= derive_cop_class
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def cop_class=(cop_class)
|
|
173
|
+
@cop_class = cop_class
|
|
174
|
+
|
|
175
|
+
reset_memoization
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def derive_cop_class
|
|
179
|
+
klass = self.class
|
|
180
|
+
|
|
181
|
+
while klass && klass != ::Minitest::Test
|
|
182
|
+
candidate = derive_cop_class_from_name(klass.name)
|
|
183
|
+
return candidate if candidate
|
|
82
184
|
|
|
83
|
-
|
|
185
|
+
klass = klass.superclass
|
|
84
186
|
end
|
|
187
|
+
|
|
188
|
+
nil
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def derive_cop_class_from_name(test_class_name)
|
|
192
|
+
return unless test_class_name
|
|
193
|
+
|
|
194
|
+
cop_name = test_class_name.delete_suffix('Test')
|
|
195
|
+
return if cop_name.empty?
|
|
196
|
+
|
|
197
|
+
constant_from(Object, cop_name) || constant_from(RuboCop::Cop::Minitest, cop_name.split('::').last)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def constant_from(namespace, constant_name)
|
|
201
|
+
return unless namespace.const_defined?(constant_name)
|
|
202
|
+
|
|
203
|
+
candidate = namespace.const_get(constant_name)
|
|
204
|
+
|
|
205
|
+
candidate if candidate.is_a?(Class) && candidate < RuboCop::Cop::Base
|
|
85
206
|
end
|
|
86
207
|
|
|
87
208
|
def format_offense(source, **replacements)
|
|
@@ -97,7 +218,7 @@ module RuboCop
|
|
|
97
218
|
def assert_no_offenses(source, file = nil)
|
|
98
219
|
setup_assertion
|
|
99
220
|
|
|
100
|
-
offenses = inspect_source(source,
|
|
221
|
+
offenses = inspect_source(source, file)
|
|
101
222
|
|
|
102
223
|
expected_annotations = RuboCop::RSpec::ExpectOffense::AnnotatedSource.parse(source)
|
|
103
224
|
actual_annotations = expected_annotations.with_offense_annotations(offenses)
|
|
@@ -180,19 +301,15 @@ module RuboCop
|
|
|
180
301
|
RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {}
|
|
181
302
|
end
|
|
182
303
|
|
|
183
|
-
def inspect_source(source,
|
|
304
|
+
def inspect_source(source, file = nil)
|
|
184
305
|
processed_source = parse_source!(source, file)
|
|
185
306
|
raise 'Error parsing example code' unless processed_source.valid_syntax?
|
|
186
307
|
|
|
187
308
|
_investigate(cop, processed_source)
|
|
188
309
|
end
|
|
189
310
|
|
|
190
|
-
def investigate(
|
|
191
|
-
|
|
192
|
-
Array(cop.class.joining_forces).each { |force| needed[force] << cop }
|
|
193
|
-
forces = needed.map do |force_class, joining_cops|
|
|
194
|
-
force_class.new(joining_cops)
|
|
195
|
-
end
|
|
311
|
+
def investigate(processed_source)
|
|
312
|
+
forces = Array(cop.class.joining_forces).map { |force_class| force_class.new([cop]) }
|
|
196
313
|
|
|
197
314
|
commissioner = RuboCop::Cop::Commissioner.new([cop], forces, raise_error: true)
|
|
198
315
|
commissioner.investigate(processed_source)
|
|
@@ -206,7 +323,7 @@ module RuboCop
|
|
|
206
323
|
file = file.path
|
|
207
324
|
end
|
|
208
325
|
|
|
209
|
-
processed_source = RuboCop::ProcessedSource.new(source,
|
|
326
|
+
processed_source = RuboCop::ProcessedSource.new(source, target_ruby_version, file, parser_engine: parser_engine)
|
|
210
327
|
processed_source.config = configuration
|
|
211
328
|
processed_source.registry = registry
|
|
212
329
|
processed_source
|
|
@@ -216,22 +333,71 @@ module RuboCop
|
|
|
216
333
|
@configuration ||= if defined?(config)
|
|
217
334
|
config
|
|
218
335
|
else
|
|
219
|
-
RuboCop::Config.new(
|
|
336
|
+
RuboCop::Config.new(configuration_hash, "#{Dir.pwd}/.rubocop.yml")
|
|
220
337
|
end
|
|
221
338
|
end
|
|
222
339
|
|
|
340
|
+
def configuration_hash
|
|
341
|
+
RuboCop::Minitest::AssertOffense.integrate_plugins!
|
|
342
|
+
|
|
343
|
+
hash = { 'AllCops' => { 'TargetRubyVersion' => target_ruby_version } }
|
|
344
|
+
if cop_class
|
|
345
|
+
hash[cop_class.cop_name] = RuboCop::ConfigLoader.default_configuration.for_cop(cop_class).merge(
|
|
346
|
+
'Enabled' => true, 'AutoCorrect' => 'always'
|
|
347
|
+
).merge(cop_config)
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
hash.merge(other_cops)
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def cop_config
|
|
354
|
+
@cop_config ||= {}
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def cop_config=(config)
|
|
358
|
+
@cop_config = config
|
|
359
|
+
|
|
360
|
+
reset_memoization
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def other_cops
|
|
364
|
+
@other_cops ||= {}
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def other_cops=(other_cops)
|
|
368
|
+
@other_cops = other_cops
|
|
369
|
+
|
|
370
|
+
reset_memoization
|
|
371
|
+
end
|
|
372
|
+
|
|
223
373
|
def registry
|
|
224
374
|
@registry ||= begin
|
|
225
375
|
cops = configuration.keys.map { |cop| RuboCop::Cop::Registry.global.find_by_cop_name(cop) }
|
|
226
|
-
cops << cop_class if
|
|
376
|
+
cops << cop_class if cop_class && !cops.include?(cop_class)
|
|
227
377
|
cops.compact!
|
|
228
378
|
RuboCop::Cop::Registry.new(cops)
|
|
229
379
|
end
|
|
230
380
|
end
|
|
231
381
|
|
|
232
|
-
def
|
|
382
|
+
def target_ruby_version
|
|
233
383
|
# Prism is the default backend parser for Ruby 3.4+.
|
|
234
|
-
ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.4 : RuboCop::TargetRuby::DEFAULT_VERSION
|
|
384
|
+
@target_ruby_version ||= (ENV['PARSER_ENGINE'] == 'parser_prism' ? 3.4 : RuboCop::TargetRuby::DEFAULT_VERSION)
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
def target_ruby_version=(version)
|
|
388
|
+
@target_ruby_version = version
|
|
389
|
+
|
|
390
|
+
reset_memoization
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
def reset_memoization
|
|
394
|
+
@cop = nil
|
|
395
|
+
@configuration = nil
|
|
396
|
+
@registry = nil
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
def ruby_version
|
|
400
|
+
target_ruby_version
|
|
235
401
|
end
|
|
236
402
|
|
|
237
403
|
def parser_engine
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rubocop'
|
|
4
|
+
require 'minitest'
|
|
5
|
+
require_relative 'minitest/assert_offense'
|
|
6
|
+
|
|
7
|
+
module RuboCop
|
|
8
|
+
# Base test case class for testing custom cops with Minitest.
|
|
9
|
+
#
|
|
10
|
+
# @example Usage
|
|
11
|
+
#
|
|
12
|
+
# class MyCopTest < RuboCop::TestCase
|
|
13
|
+
# def test_registers_offense
|
|
14
|
+
# assert_offense(<<~RUBY)
|
|
15
|
+
# bad_method
|
|
16
|
+
# ^^^^^^^^^^ Use `good_method` instead of `bad_method`.
|
|
17
|
+
# RUBY
|
|
18
|
+
#
|
|
19
|
+
# assert_correction(<<~RUBY)
|
|
20
|
+
# good_method
|
|
21
|
+
# RUBY
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# See the documentation of `RuboCop::Minitest::AssertOffense` for details.
|
|
26
|
+
class TestCase < ::Minitest::Test
|
|
27
|
+
include RuboCop::Minitest::AssertOffense
|
|
28
|
+
end
|
|
29
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubocop-minitest
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.40.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bozhidar Batsov
|
|
@@ -145,13 +145,14 @@ files:
|
|
|
145
145
|
- lib/rubocop/minitest/plugin.rb
|
|
146
146
|
- lib/rubocop/minitest/support.rb
|
|
147
147
|
- lib/rubocop/minitest/version.rb
|
|
148
|
+
- lib/rubocop/test_case.rb
|
|
148
149
|
licenses:
|
|
149
150
|
- MIT
|
|
150
151
|
metadata:
|
|
151
152
|
homepage_uri: https://docs.rubocop.org/rubocop-minitest/
|
|
152
153
|
changelog_uri: https://github.com/rubocop/rubocop-minitest/blob/master/CHANGELOG.md
|
|
153
154
|
source_code_uri: https://github.com/rubocop/rubocop-minitest
|
|
154
|
-
documentation_uri: https://docs.rubocop.org/rubocop-minitest/0.
|
|
155
|
+
documentation_uri: https://docs.rubocop.org/rubocop-minitest/0.40
|
|
155
156
|
bug_tracker_uri: https://github.com/rubocop/rubocop-minitest/issues
|
|
156
157
|
rubygems_mfa_required: 'true'
|
|
157
158
|
default_lint_roller_plugin: RuboCop::Minitest::Plugin
|
|
@@ -169,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
169
170
|
- !ruby/object:Gem::Version
|
|
170
171
|
version: '0'
|
|
171
172
|
requirements: []
|
|
172
|
-
rubygems_version: 4.0.
|
|
173
|
+
rubygems_version: 4.0.16
|
|
173
174
|
specification_version: 4
|
|
174
175
|
summary: Automatic Minitest code style checking tool.
|
|
175
176
|
test_files: []
|