chutney 3.12.4 → 3.14.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/chutney.gemspec +1 -1
- data/config/chutney_defaults.yml +5 -0
- data/docs/usage/rules.md +2 -0
- data/lib/chutney/linter/avoid_tags.rb +36 -0
- data/lib/chutney/linter/same_scenario.rb +11 -11
- data/lib/chutney/linter/too_short_tag.rb +22 -0
- data/lib/chutney/version.rb +1 -1
- data/lib/chutney.rb +2 -0
- data/lib/config/locales/en.yml +4 -0
- data/usechutney.com.site/site/src/docs/rules/avoid-tags.md +38 -0
- data/usechutney.com.site/site/src/docs/rules/index.page.md +1 -0
- data/usechutney.com.site/site/src/docs/rules/too_short_tag.page.md +25 -0
- metadata +9 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c21346027cfc0954890e1e287dbf282e76567e58267f9da730d2132d0ae83e1
|
|
4
|
+
data.tar.gz: d0a823dcd25b1bccc00bc873444f079e1be6421aad287c624a26fd3b6e11dac2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 77880b9602738619b732d6eeee96a05cab06177c159fce4b0a150af9684d166e65314408548edaf42cc735cb93eef88164338ec32561210c19a9cabe3a22ab38
|
|
7
|
+
data.tar.gz: 3e650442d104bd17c8cdffbc5956291e9cb288a4b0fbca34cbdb0dc6c6b7413e8ed40bff9d4272e48aebc6062bb459c89f627f08fa29660fbc1e279f967bf5dd
|
data/chutney.gemspec
CHANGED
|
@@ -48,7 +48,7 @@ Gem::Specification.new do |spec|
|
|
|
48
48
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
49
49
|
spec.require_paths = ['lib']
|
|
50
50
|
|
|
51
|
-
spec.add_dependency 'amatch', '>= 0.4', '< 0.
|
|
51
|
+
spec.add_dependency 'amatch', '>= 0.4', '< 0.8'
|
|
52
52
|
spec.add_dependency 'cuke_modeler', '~> 3.26'
|
|
53
53
|
spec.add_dependency 'i18n', '>= 1.8.2', '< 1.15.0'
|
|
54
54
|
spec.add_dependency 'fast-mcp', '~> 1.5'
|
data/config/chutney_defaults.yml
CHANGED
|
@@ -12,6 +12,8 @@ AvoidSplatStepsInBackground:
|
|
|
12
12
|
Enabled: true
|
|
13
13
|
AvoidSplatStepsInScenarios:
|
|
14
14
|
Enabled: true
|
|
15
|
+
AvoidTags:
|
|
16
|
+
Enabled: false
|
|
15
17
|
AvoidTypographersQuotes:
|
|
16
18
|
Enabled: true
|
|
17
19
|
BackgroundDoesMoreThanSetup:
|
|
@@ -74,6 +76,9 @@ TooManyTags:
|
|
|
74
76
|
TooLongStep:
|
|
75
77
|
Enabled: true
|
|
76
78
|
MaxLength: 80
|
|
79
|
+
TooShortTag:
|
|
80
|
+
Enabled: true
|
|
81
|
+
MinLength: 2
|
|
77
82
|
UniqueScenarioNames:
|
|
78
83
|
Enabled: true
|
|
79
84
|
UnknownVariable:
|
data/docs/usage/rules.md
CHANGED
|
@@ -19,6 +19,8 @@ Chutney enforces its rules with the linters. These are:
|
|
|
19
19
|
|
|
20
20
|
[AvoidSplatStepsInScenarios](https://github.com/BillyRuffian/chutney/blob/master/features/avoid_splat_steps_in_scenarios.feature): The Scenario contains a splat step. It should only contain named steps.
|
|
21
21
|
|
|
22
|
+
[AvoidTags](https://github.com/BillyRuffian/chutney/blob/master/features/avoid_tags.feature): The Feature file contains tags to avoid.
|
|
23
|
+
|
|
22
24
|
[AvoidTypographersQuotes](https://github.com/BillyRuffian/chutney/blob/master/features/avoid_typographers_quotes.feature): Cutting and pasting from Word documents? Is that pasting in curly-quotes instead of neutral ones you would type on a keyboard? Are you sure that's what you want?
|
|
23
25
|
|
|
24
26
|
[BackgroundDoesMoreThanSetup](https://github.com/BillyRuffian/chutney/blob/master/features/background_does_more_than_setup.feature): Background in feature files should only do setup activity and so they should only contain `Given` steps.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Chutney
|
|
4
|
+
# service class to lint for avoiding tags
|
|
5
|
+
class AvoidTags < Linter
|
|
6
|
+
def lint
|
|
7
|
+
return if feature.nil?
|
|
8
|
+
|
|
9
|
+
feature_tags = tags_for(feature)
|
|
10
|
+
feature_tags_to_avoid_found = feature_tags & tags_to_avoid
|
|
11
|
+
|
|
12
|
+
unless feature_tags_to_avoid_found.empty?
|
|
13
|
+
feature_tags_to_avoid_found = feature_tags_to_avoid_found.map { |tag| tag.prepend('@') }
|
|
14
|
+
add_issue(I18n.t('linters.avoid_tags', tags: feature_tags_to_avoid_found.join(', ')), feature)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
scenarios do |_feature, scenario|
|
|
18
|
+
scenario_tags = tags_for(scenario)
|
|
19
|
+
scenario_tags_to_avoid_found = scenario_tags & tags_to_avoid
|
|
20
|
+
|
|
21
|
+
unless scenario_tags_to_avoid_found.empty?
|
|
22
|
+
scenario_tags_to_avoid_found = scenario_tags_to_avoid_found.map { |tag| tag.prepend('@') }
|
|
23
|
+
add_issue(I18n.t('linters.avoid_tags', tags: scenario_tags_to_avoid_found.join(', ')), feature, scenario)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def tags_to_avoid
|
|
29
|
+
tags_to_avoid = configuration['Tags'] || []
|
|
30
|
+
|
|
31
|
+
return [] unless tags_to_avoid.is_a?(Array)
|
|
32
|
+
|
|
33
|
+
tags_to_avoid
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -13,7 +13,7 @@ module Chutney
|
|
|
13
13
|
|
|
14
14
|
def lint # rubocop:disable Metrics/MethodLength
|
|
15
15
|
scenarios do |feature, scenario|
|
|
16
|
-
text = background ? background.steps.
|
|
16
|
+
text = background ? background.steps.join("\n").concat("\n") : ''
|
|
17
17
|
text += scenario
|
|
18
18
|
.steps
|
|
19
19
|
.map { |step| "#{step.text} #{child_text(step)}" }
|
|
@@ -23,16 +23,16 @@ module Chutney
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
SameScenario.dictionary.filter { |_k, v| v.size > 1 }
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
.each_value do |v|
|
|
27
|
+
v[1...].each_with_index do |problem, index|
|
|
28
|
+
add_issue(I18n.t('linters.same_scenario',
|
|
29
|
+
feature: problem[:feature].name,
|
|
30
|
+
scenario: problem[:scenario].name,
|
|
31
|
+
original_feature: v.first[:feature].name,
|
|
32
|
+
original_scenario: v.first[:scenario].name),
|
|
33
|
+
problem[:feature], problem[:scenario], nil)
|
|
34
|
+
v.delete_at(index + 1)
|
|
35
|
+
end
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Chutney
|
|
4
|
+
# service class to lint for tags that are too short, such as @t
|
|
5
|
+
class TooShortTag < Linter
|
|
6
|
+
def lint
|
|
7
|
+
scenarios do |feature, scenario|
|
|
8
|
+
tags = tags_for(feature) + tags_for(scenario)
|
|
9
|
+
next unless tags.any? { |tag| tag.length < min_length }
|
|
10
|
+
|
|
11
|
+
add_issue(
|
|
12
|
+
I18n.t('linters.too_short_tag', min_length:, tags:),
|
|
13
|
+
feature
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def min_length
|
|
19
|
+
configuration['MinLength']&.to_i || 2
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
data/lib/chutney/version.rb
CHANGED
data/lib/chutney.rb
CHANGED
|
@@ -11,6 +11,7 @@ require 'chutney/linter/avoid_outline_for_single_example'
|
|
|
11
11
|
require 'chutney/linter/avoid_scripting'
|
|
12
12
|
require 'chutney/linter/avoid_splat_steps_in_background'
|
|
13
13
|
require 'chutney/linter/avoid_splat_steps_in_scenarios'
|
|
14
|
+
require 'chutney/linter/avoid_tags'
|
|
14
15
|
require 'chutney/linter/avoid_typographers_quotes'
|
|
15
16
|
require 'chutney/linter/background_does_more_than_setup'
|
|
16
17
|
require 'chutney/linter/background_requires_multiple_scenarios'
|
|
@@ -40,6 +41,7 @@ require 'chutney/linter/too_long_step'
|
|
|
40
41
|
require 'chutney/linter/too_many_different_tags'
|
|
41
42
|
require 'chutney/linter/too_many_steps'
|
|
42
43
|
require 'chutney/linter/too_many_tags'
|
|
44
|
+
require 'chutney/linter/too_short_tag'
|
|
43
45
|
require 'chutney/linter/unique_scenario_names'
|
|
44
46
|
require 'chutney/linter/unknown_variable'
|
|
45
47
|
require 'chutney/linter/unused_variable'
|
data/lib/config/locales/en.yml
CHANGED
|
@@ -19,6 +19,8 @@ en:
|
|
|
19
19
|
The Background contains a splat step. It should only contain named steps.
|
|
20
20
|
avoid_splat_steps_in_scenarios: >-
|
|
21
21
|
The Scenario contains a splat step. It should only contain named steps.
|
|
22
|
+
avoid_tags: >-
|
|
23
|
+
The following tags are not allowed: %{tags}.
|
|
22
24
|
avoid_typographers_quotes: >-
|
|
23
25
|
You are using typographers quotation marks (curly quotes).
|
|
24
26
|
Make sure you intend to use this character and not a neutral quote
|
|
@@ -108,6 +110,8 @@ en:
|
|
|
108
110
|
There are too many steps in this feature. There are %{count} and the maximum is %{max}.
|
|
109
111
|
too_many_tags: >-
|
|
110
112
|
There are too many tags in this feature. There are %{count} and the maximum is %{max}.
|
|
113
|
+
too_short_tag: >-
|
|
114
|
+
Your tag is too short: %{tags}. The minimum length of a tag is %{min_length}. Tags should have meaning.
|
|
111
115
|
unique_scenario_names: >-
|
|
112
116
|
The scenario name '%{name}' is duplicated, first used at line %{line}, column %{column}.
|
|
113
117
|
unknown_variable: >-
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Avoid Tags
|
|
2
|
+
|
|
3
|
+
Sometimes you just need a tag for you... maybe to filter your scenarios for focused testing?... or maybe you've got some fancy after hook to help with debugging?
|
|
4
|
+
Whatever the reason, you probably didn't mean to commit that to source.
|
|
5
|
+
|
|
6
|
+
AvoidTags helps prevent the accidental commit of tags by warning you if you have any tags in your feature file which match a configurable list of tags to avoid.
|
|
7
|
+
|
|
8
|
+
## Configuration
|
|
9
|
+
|
|
10
|
+
```yaml
|
|
11
|
+
AvoidTags:
|
|
12
|
+
Enabled: true
|
|
13
|
+
Tags:
|
|
14
|
+
- MyFancyDebugTag
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Bad
|
|
18
|
+
|
|
19
|
+
```gherkin
|
|
20
|
+
@MyFancyDebugTag
|
|
21
|
+
Scenario: Log in with valid credentials
|
|
22
|
+
Given I have visited the website
|
|
23
|
+
And I have logged in
|
|
24
|
+
And I have viewed sale items
|
|
25
|
+
When I view special offers
|
|
26
|
+
Then I will see my discount code
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Good
|
|
30
|
+
|
|
31
|
+
```gherkin
|
|
32
|
+
Scenario: Log in with valid credentials
|
|
33
|
+
Given I have visited the website
|
|
34
|
+
And I have logged in
|
|
35
|
+
And I have viewed sale items
|
|
36
|
+
When I view special offers
|
|
37
|
+
Then I will see my discount code
|
|
38
|
+
```
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
* [Too Many Different Tags](/docs/rules/too-many-different-tags)
|
|
37
37
|
* [Too Many Steps](/docs/rules/too-many-steps)
|
|
38
38
|
* [Too Many Tags](/docs/rules/too-many-tags)
|
|
39
|
+
* [Too Short Tag](/docs/rules/too_short_tag)
|
|
39
40
|
* [Unique Scenario Names](/docs/rules/unique-scenario-names)
|
|
40
41
|
* [Unknown Variable](/docs/rules/unknown-variable)
|
|
41
42
|
* [Unused Variable](/docs/rules/unused-variable)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Too Short Tag
|
|
2
|
+
|
|
3
|
+
If you have used a tag that is too short, you have probably done it while locally testing. This is a bad practice because it makes your tests harder to read and maintain.
|
|
4
|
+
|
|
5
|
+
It is much better to use tags that relate to the test, such as a ticket number to connect the development work you are testing
|
|
6
|
+
|
|
7
|
+
## Bad
|
|
8
|
+
|
|
9
|
+
```gherkin
|
|
10
|
+
@t
|
|
11
|
+
Scenario: Log in with valid credentials
|
|
12
|
+
Given I have visited the website
|
|
13
|
+
When I log in with "user1" and "pass1"
|
|
14
|
+
Then I will see my account
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Good
|
|
18
|
+
|
|
19
|
+
```gherkin
|
|
20
|
+
@QE-0001
|
|
21
|
+
Scenario: Log in with valid credentials
|
|
22
|
+
Given I have visited the website
|
|
23
|
+
When I log in with "user1" and "pass1"
|
|
24
|
+
Then I will see my account
|
|
25
|
+
```
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: chutney
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nigel Brookes-Thomas
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
- John Gluck
|
|
11
11
|
bindir: exe
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date:
|
|
13
|
+
date: 2026-06-11 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: amatch
|
|
@@ -21,7 +21,7 @@ dependencies:
|
|
|
21
21
|
version: '0.4'
|
|
22
22
|
- - "<"
|
|
23
23
|
- !ruby/object:Gem::Version
|
|
24
|
-
version: '0.
|
|
24
|
+
version: '0.8'
|
|
25
25
|
type: :runtime
|
|
26
26
|
prerelease: false
|
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -31,7 +31,7 @@ dependencies:
|
|
|
31
31
|
version: '0.4'
|
|
32
32
|
- - "<"
|
|
33
33
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: '0.
|
|
34
|
+
version: '0.8'
|
|
35
35
|
- !ruby/object:Gem::Dependency
|
|
36
36
|
name: cuke_modeler
|
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -183,6 +183,7 @@ files:
|
|
|
183
183
|
- lib/chutney/linter/avoid_scripting.rb
|
|
184
184
|
- lib/chutney/linter/avoid_splat_steps_in_background.rb
|
|
185
185
|
- lib/chutney/linter/avoid_splat_steps_in_scenarios.rb
|
|
186
|
+
- lib/chutney/linter/avoid_tags.rb
|
|
186
187
|
- lib/chutney/linter/avoid_typographers_quotes.rb
|
|
187
188
|
- lib/chutney/linter/background_does_more_than_setup.rb
|
|
188
189
|
- lib/chutney/linter/background_requires_multiple_scenarios.rb
|
|
@@ -212,6 +213,7 @@ files:
|
|
|
212
213
|
- lib/chutney/linter/too_many_different_tags.rb
|
|
213
214
|
- lib/chutney/linter/too_many_steps.rb
|
|
214
215
|
- lib/chutney/linter/too_many_tags.rb
|
|
216
|
+
- lib/chutney/linter/too_short_tag.rb
|
|
215
217
|
- lib/chutney/linter/unique_scenario_names.rb
|
|
216
218
|
- lib/chutney/linter/unknown_variable.rb
|
|
217
219
|
- lib/chutney/linter/unused_variable.rb
|
|
@@ -250,6 +252,7 @@ files:
|
|
|
250
252
|
- usechutney.com.site/site/src/docs/rules/avoid-scripting.page.md
|
|
251
253
|
- usechutney.com.site/site/src/docs/rules/avoid-splat-steps-in-background.page.md
|
|
252
254
|
- usechutney.com.site/site/src/docs/rules/avoid-splat-steps-in-scenarios.page.md
|
|
255
|
+
- usechutney.com.site/site/src/docs/rules/avoid-tags.md
|
|
253
256
|
- usechutney.com.site/site/src/docs/rules/avoid-typographers-quotes.page.md
|
|
254
257
|
- usechutney.com.site/site/src/docs/rules/background-does-more-than-setup.page.md
|
|
255
258
|
- usechutney.com.site/site/src/docs/rules/background-requires-multiple-scenarios.page.md
|
|
@@ -280,6 +283,7 @@ files:
|
|
|
280
283
|
- usechutney.com.site/site/src/docs/rules/too-many-different-tags.page.md
|
|
281
284
|
- usechutney.com.site/site/src/docs/rules/too-many-steps.page.md
|
|
282
285
|
- usechutney.com.site/site/src/docs/rules/too-many-tags.page.md
|
|
286
|
+
- usechutney.com.site/site/src/docs/rules/too_short_tag.page.md
|
|
283
287
|
- usechutney.com.site/site/src/docs/rules/unique-scenario-names.page.md
|
|
284
288
|
- usechutney.com.site/site/src/docs/rules/unknown-variable.page.md
|
|
285
289
|
- usechutney.com.site/site/src/docs/rules/unused-variable.page.md
|
|
@@ -311,7 +315,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
311
315
|
- !ruby/object:Gem::Version
|
|
312
316
|
version: '0'
|
|
313
317
|
requirements: []
|
|
314
|
-
rubygems_version: 4.0.
|
|
318
|
+
rubygems_version: 4.0.10
|
|
315
319
|
specification_version: 4
|
|
316
320
|
summary: A linter for multi-lingual Gherkin
|
|
317
321
|
test_files: []
|