cuke_linter 0.11.1 → 0.12.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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -1
  3. data/CHANGELOG.md +13 -2
  4. data/LICENSE.txt +1 -1
  5. data/appveyor.yml +19 -0
  6. data/cuke_linter.gemspec +1 -1
  7. data/environments/rspec_env.rb +4 -0
  8. data/lib/cuke_linter.rb +6 -0
  9. data/lib/cuke_linter/linters/element_with_common_tags_linter.rb +41 -0
  10. data/lib/cuke_linter/linters/element_with_duplicate_tags_linter.rb +44 -0
  11. data/lib/cuke_linter/linters/feature_file_with_mismatched_name_linter.rb +26 -0
  12. data/lib/cuke_linter/version.rb +1 -1
  13. data/testing/cucumber/features/command_line.feature +7 -7
  14. data/testing/cucumber/features/default_linters.feature +3 -0
  15. data/testing/cucumber/features/linters/element_with_common_tags.feature +28 -0
  16. data/testing/cucumber/features/linters/element_with_duplicate_tags.feature +71 -0
  17. data/testing/cucumber/features/linters/feature_file_with_mismatched_name.feature +32 -0
  18. data/testing/cucumber/step_definitions/setup_steps.rb +25 -0
  19. data/testing/gemfiles/cuke_modeler1.gemfile +8 -0
  20. data/testing/gemfiles/cuke_modeler2.gemfile +8 -0
  21. data/testing/model_factory.rb +14 -2
  22. data/testing/rspec/spec/integration/cli_integration_spec.rb +8 -7
  23. data/testing/rspec/spec/integration/cuke_linter_integration_spec.rb +5 -0
  24. data/testing/rspec/spec/integration/linters/element_with_common_tags_linter_integration_spec.rb +8 -0
  25. data/testing/rspec/spec/integration/linters/element_with_duplicate_tags_linter_integration_spec.rb +8 -0
  26. data/testing/rspec/spec/integration/linters/feature_file_with_mismatched_name_integration_spec.rb +8 -0
  27. data/testing/rspec/spec/unit/linters/element_with_common_tags_linter_unit_spec.rb +248 -0
  28. data/testing/rspec/spec/unit/linters/element_with_duplicate_tags_linter_unit_spec.rb +203 -0
  29. data/testing/rspec/spec/unit/linters/element_with_too_many_tags_linter_unit_spec.rb +1 -4
  30. data/testing/rspec/spec/unit/linters/feature_file_with_invalid_name_linter_unit_spec.rb +1 -1
  31. data/testing/rspec/spec/unit/linters/feature_file_with_mismatched_name_linter_unit_spec.rb +124 -0
  32. metadata +24 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 05f9639710a8ee90502992efd3bf5a0cd23d989e10f8b2699ca2120c25729c64
4
- data.tar.gz: 6aeae6c4a917210bc09de39b0d751de4c0c15c929478dd362f65c6ac3e88dc70
3
+ metadata.gz: 2f5b4c792db279ecfb0eab3df8591ca772891edfe1f156daae3fd1715d74cda9
4
+ data.tar.gz: 572b6d392046c43da411458e0f3ac23e32ee4bd82bfacadcf98e0268120235a0
5
5
  SHA512:
6
- metadata.gz: 6e11d0529be4f2202de3f98bf2cf7149822fd2378f5ec18de2b4c2a0cbdc56f7b8534614de911ffd570823e4faf0ffb06ceed31df392a37ab7911c1edd1c3715
7
- data.tar.gz: c5152f78a6092267fe7050445c72864807cd70ce61af044292c5af3be5a91e180d236680ca3e3622795417d08e1c47ada1bbfcaf8cb99a7607df8a22f91e5885
6
+ metadata.gz: ff8ed351d8fe31419a1cc922e3430eda5a84e88d8bda09838095c1cd647bf56826a121f0eb335527a03b2ccb35a6e399d3a4f34e09dcef998860228a2fcd9a14
7
+ data.tar.gz: f0739486ca0c93b175e5bd34c0b7334c360331bd8e2e9472055bd53a2ed4acde21b7db9f5f53b70a3f852c2d093e39f4193aa473a45e869e23ecda086019fa0f
@@ -8,12 +8,16 @@ dist: trusty
8
8
 
9
9
  language: ruby
10
10
  rvm:
11
- - 2.3.3
12
11
  - 2.4.0
13
12
  - 2.5.1
14
13
  - 2.6.0
15
14
  - jruby-9.1.7.0
16
15
 
16
+
17
+ gemfile:
18
+ - testing/gemfiles/cuke_modeler1.gemfile
19
+ - testing/gemfiles/cuke_modeler2.gemfile
20
+
17
21
  before_install: gem install bundler -v 1.16.2
18
22
 
19
23
  script: bundle exec rake cuke_linter:ci_build
@@ -6,7 +6,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- Nothing yet... *(see development branch)*
9
+ Nothing yet...
10
+
11
+ ## [0.12.0] - 2020-02-13
12
+
13
+ ### Added
14
+ - New linters
15
+ - ElementWithCommonTagsLinter
16
+ - ElementWithDuplicateTagsLinter
17
+ - FeatureFileWithMismatchedNameLinter
18
+
19
+ - Now compatible with CukeModeler 2.x
10
20
 
11
21
 
12
22
  ## [0.11.1] - 2019-11-07
@@ -119,7 +129,8 @@ Nothing yet... *(see development branch)*
119
129
  - Custom linters, formatters, and command line usability
120
130
 
121
131
 
122
- [Unreleased]: https://github.com/enkessler/cuke_linter/compare/v0.11.1...HEAD
132
+ [Unreleased]: https://github.com/enkessler/cuke_linter/compare/v0.12.0...HEAD
133
+ [0.12.0]: https://github.com/enkessler/cuke_linter/compare/v0.11.1...v0.12.0
123
134
  [0.11.1]: https://github.com/enkessler/cuke_linter/compare/v0.11.0...v0.11.1
124
135
  [0.11.0]: https://github.com/enkessler/cuke_linter/compare/v0.10.0...v0.11.0
125
136
  [0.10.0]: https://github.com/enkessler/cuke_linter/compare/v0.9.0...v0.10.0
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018-2019 Eric Kessler
3
+ Copyright (c) 2018-2020 Eric Kessler
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -3,11 +3,30 @@ version: '1.0.{build}'
3
3
  environment:
4
4
  matrix:
5
5
  - RUBY_VERSION: 23
6
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler1.gemfile
6
7
  - RUBY_VERSION: 23-x64
8
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler1.gemfile
7
9
  - RUBY_VERSION: 24
10
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler1.gemfile
8
11
  - RUBY_VERSION: 24-x64
12
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler1.gemfile
9
13
  - RUBY_VERSION: 25
14
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler1.gemfile
10
15
  - RUBY_VERSION: 25-x64
16
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler1.gemfile
17
+
18
+ - RUBY_VERSION: 23
19
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler2.gemfile
20
+ - RUBY_VERSION: 23-x64
21
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler2.gemfile
22
+ - RUBY_VERSION: 24
23
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler2.gemfile
24
+ - RUBY_VERSION: 24-x64
25
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler2.gemfile
26
+ - RUBY_VERSION: 25
27
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler2.gemfile
28
+ - RUBY_VERSION: 25-x64
29
+ BUNDLE_GEMFILE: testing/gemfiles/cuke_modeler2.gemfile
11
30
 
12
31
  install:
13
32
  - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH%
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.required_ruby_version = '~> 2.0'
28
28
 
29
- spec.add_runtime_dependency 'cuke_modeler', '~> 1.5'
29
+ spec.add_runtime_dependency 'cuke_modeler', '>= 1.5', '< 3.0'
30
30
 
31
31
  spec.add_development_dependency "bundler", "< 3.0"
32
32
  spec.add_development_dependency "cucumber", "~> 3.0"
@@ -12,6 +12,10 @@ require_relative '../testing/rspec/spec/unit/linters/linter_unit_specs'
12
12
  require_relative '../testing/rspec/spec/integration/formatters/formatter_integration_specs'
13
13
  require_relative '../testing/rspec/spec/integration/linters/linter_integration_specs'
14
14
 
15
+ # Convenient constants, just in case what kinds of elements are taggable ever changes
16
+ TAGGABLE_ELEMENTS = ['feature', 'scenario', 'outline', 'example']
17
+ ELEMENTS_WITH_TAGGABLE_CHILDREN = ['feature', 'outline']
18
+
15
19
  RSpec.configure do |config|
16
20
  # Enable flags like --only-failures and --next-failure
17
21
  config.example_status_persistence_file_path = ".rspec_status"
@@ -5,9 +5,12 @@ require "cuke_linter/version"
5
5
  require 'cuke_linter/formatters/pretty_formatter'
6
6
  require 'cuke_linter/linters/linter'
7
7
  require 'cuke_linter/linters/background_does_more_than_setup_linter'
8
+ require 'cuke_linter/linters/element_with_common_tags_linter'
9
+ require 'cuke_linter/linters/element_with_duplicate_tags_linter'
8
10
  require 'cuke_linter/linters/element_with_too_many_tags_linter'
9
11
  require 'cuke_linter/linters/example_without_name_linter'
10
12
  require 'cuke_linter/linters/feature_file_with_invalid_name_linter'
13
+ require 'cuke_linter/linters/feature_file_with_mismatched_name_linter'
11
14
  require 'cuke_linter/linters/feature_with_too_many_different_tags_linter'
12
15
  require 'cuke_linter/linters/feature_without_name_linter'
13
16
  require 'cuke_linter/linters/feature_without_description_linter'
@@ -33,9 +36,12 @@ require 'cuke_linter/linters/test_with_too_many_steps_linter'
33
36
  module CukeLinter
34
37
 
35
38
  @original_linters = { 'BackgroundDoesMoreThanSetupLinter' => BackgroundDoesMoreThanSetupLinter.new,
39
+ 'ElementWithCommonTagsLinter' => ElementWithCommonTagsLinter.new,
40
+ 'ElementWithDuplicateTagsLinter' => ElementWithDuplicateTagsLinter.new,
36
41
  'ElementWithTooManyTagsLinter' => ElementWithTooManyTagsLinter.new,
37
42
  'ExampleWithoutNameLinter' => ExampleWithoutNameLinter.new,
38
43
  'FeatureFileWithInvalidNameLinter' => FeatureFileWithInvalidNameLinter.new,
44
+ 'FeatureFileWithMismatchedNameLinter' => FeatureFileWithMismatchedNameLinter.new,
39
45
  'FeatureWithTooManyDifferentTagsLinter' => FeatureWithTooManyDifferentTagsLinter.new,
40
46
  'FeatureWithoutDescriptionLinter' => FeatureWithoutDescriptionLinter.new,
41
47
  'FeatureWithoutNameLinter' => FeatureWithoutNameLinter.new,
@@ -0,0 +1,41 @@
1
+ module CukeLinter
2
+
3
+ # A linter that detects Gherkin elements that have the same tag on all of their taggable child elements
4
+
5
+ class ElementWithCommonTagsLinter < Linter
6
+
7
+ # The rule used to determine if a model has a problem
8
+ def rule(model)
9
+ return false unless model.is_a?(CukeModeler::Feature) || model.is_a?(CukeModeler::Outline)
10
+
11
+ @linted_model_class = model.class
12
+
13
+ child_accessor_method = model.is_a?(CukeModeler::Feature) ? :tests : :examples
14
+ child_models = model.send(child_accessor_method) || []
15
+
16
+ tag_sets = child_models.collect { |child_model| child_model.tags || [] }
17
+ tag_name_sets = tag_sets.collect { |tags| tags.map(&:name) }
18
+
19
+ return false if tag_name_sets.count < 2
20
+
21
+ @common_tag = tag_name_sets.reduce(:&).first
22
+
23
+ !@common_tag.nil?
24
+ end
25
+
26
+ # The message used to describe the problem that has been found
27
+ def message
28
+ class_name = @linted_model_class.name.split('::').last
29
+
30
+ case class_name
31
+ when 'Feature'
32
+ "All tests in #{class_name} have tag '#{@common_tag}'. Move tag to #{class_name} level."
33
+ when 'Outline'
34
+ "All Examples in #{class_name} have tag '#{@common_tag}'. Move tag to #{class_name} level."
35
+ else
36
+ raise("Linted an unexpected model type '#{class_name}'!")
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,44 @@
1
+ module CukeLinter
2
+
3
+ # A linter that detects taggable Gherkin elements that have duplicate tags
4
+
5
+ class ElementWithDuplicateTagsLinter < Linter
6
+
7
+ # Changes the linting settings on the linter using the provided configuration
8
+ def configure(options)
9
+ @tag_inheritance = options['IncludeInheritedTags']
10
+ end
11
+
12
+ # The rule used to determine if a model has a problem
13
+ def rule(model)
14
+ return false unless model.is_a?(CukeModeler::Feature) ||
15
+ model.is_a?(CukeModeler::Scenario) ||
16
+ model.is_a?(CukeModeler::Outline) ||
17
+ model.is_a?(CukeModeler::Example)
18
+
19
+
20
+ @linted_model_class = model.class
21
+
22
+ if @tag_inheritance
23
+ relevant_tags = model.all_tags
24
+ else
25
+ relevant_tags = model.tags || []
26
+ end
27
+
28
+
29
+ tag_names = relevant_tags.map(&:name)
30
+
31
+ @duplicate_tag = tag_names.find { |tag| tag_names.count(tag) > 1 }
32
+
33
+ !@duplicate_tag.nil?
34
+ end
35
+
36
+ # The message used to describe the problem that has been found
37
+ def message
38
+ class_name = @linted_model_class.name.split('::').last
39
+
40
+ "#{class_name} has duplicate tag '#{@duplicate_tag}'."
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,26 @@
1
+ module CukeLinter
2
+
3
+ # A linter that detects mismatched feature file names
4
+
5
+ class FeatureFileWithMismatchedNameLinter < Linter
6
+
7
+ # The rule used to determine if a model has a problem
8
+ def rule(model)
9
+ return false unless model.is_a?(CukeModeler::FeatureFile)
10
+
11
+ file_name = File.basename(model.path, '.feature')
12
+ feature_name = model.feature.name
13
+
14
+ normalized_file_name = file_name.downcase.delete('_ -')
15
+ normalized_feature_name = feature_name.downcase.delete('_ -')
16
+
17
+ normalized_file_name != normalized_feature_name
18
+ end
19
+
20
+ # The message used to describe the problem that has been found
21
+ def message
22
+ 'Feature file name does not match feature name.'
23
+ end
24
+
25
+ end
26
+ end
@@ -1,4 +1,4 @@
1
1
  module CukeLinter
2
2
  # The release version of this gem
3
- VERSION = '0.11.1'
3
+ VERSION = '0.12.0'
4
4
  end
@@ -57,14 +57,14 @@ Feature: Using cuke_linter on the command line
57
57
  """
58
58
 
59
59
  Scenario: Specifying directories and files to lint
60
- Given the following feature file "some.feature":
60
+ Given the following feature file "some_feature.feature":
61
61
  """
62
62
  Feature: Some feature
63
63
  Scenario: A scenario
64
64
  When a step
65
65
  Then a step
66
66
  """
67
- And the following feature file "a_directory/with_a.feature":
67
+ And the following feature file "a_directory/with/some_feature.feature":
68
68
  """
69
69
  Feature: Some feature
70
70
  Scenario: A scenario
@@ -73,14 +73,14 @@ Feature: Using cuke_linter on the command line
73
73
  """
74
74
  When the following command is executed:
75
75
  """
76
- cuke_linter -p <path_to>/some.feature -p <path_to>/a_directory
76
+ cuke_linter -p <path_to>/some_feature.feature -p <path_to>/a_directory
77
77
  """
78
78
  Then the resulting output is the following:
79
79
  """
80
80
  FeatureWithoutDescriptionLinter
81
81
  Feature has no description
82
- <path_to>/a_directory/with_a.feature:1
83
- <path_to>/some.feature:1
82
+ <path_to>/a_directory/with/some_feature.feature:1
83
+ <path_to>/some_feature.feature:1
84
84
 
85
85
  2 issues found
86
86
  """
@@ -173,8 +173,8 @@ Feature: Using cuke_linter on the command line
173
173
 
174
174
  Given the following feature file "has_no_scenarios.feature":
175
175
  """
176
- Feature: This feature
177
- has no scenarios
176
+ Feature: Has no scenarios
177
+ Not a single one
178
178
  """
179
179
  And the following configuration file "my_config.file":
180
180
  """
@@ -9,9 +9,12 @@ Feature: Default Linters
9
9
  Given no other linters have been registered or unregistered
10
10
  Then the following linters are registered by default
11
11
  | BackgroundDoesMoreThanSetupLinter |
12
+ | ElementWithCommonTagsLinter |
13
+ | ElementWithDuplicateTagsLinter |
12
14
  | ElementWithTooManyTagsLinter |
13
15
  | ExampleWithoutNameLinter |
14
16
  | FeatureFileWithInvalidNameLinter |
17
+ | FeatureFileWithMismatchedNameLinter |
15
18
  | FeatureWithTooManyDifferentTagsLinter |
16
19
  | FeatureWithoutDescriptionLinter |
17
20
  | FeatureWithoutNameLinter |
@@ -0,0 +1,28 @@
1
+ Feature: Element with common tags linter
2
+
3
+ As a writer of documentation
4
+ I want taggable elements to not needlessly have the same tags
5
+ So that redundancy is minimized
6
+
7
+
8
+ Scenario: Linting
9
+
10
+ Note: Also works on outlines that have common tags on their examples
11
+
12
+ Given a linter for elements with common tags
13
+ And the following feature:
14
+ """
15
+ Feature:
16
+
17
+ @same_tag
18
+ Scenario:
19
+ * a step
20
+
21
+ @same_tag
22
+ Scenario:
23
+ * a step
24
+ """
25
+ When it is linted
26
+ Then an error is reported:
27
+ | linter | problem | location |
28
+ | ElementWithCommonTagsLinter | All tests in Feature have tag '@same_tag'. Move tag to Feature level. | <path_to_file>:1 |
@@ -0,0 +1,71 @@
1
+ Feature: Element with duplicate tags linter
2
+
3
+ As a writer of documentation
4
+ I want taggable elements to not have duplicate of tags
5
+ So that redundancy is minimized
6
+
7
+
8
+ Scenario: Linting
9
+
10
+ Note: Also works on outlines, features, and examples
11
+
12
+ Given a linter for elements with duplicate tags
13
+ And the following feature:
14
+ """
15
+ Feature:
16
+
17
+ @same_tag @a_different_tag @same_tag
18
+ Scenario:
19
+ * a step
20
+ """
21
+ When it is linted
22
+ Then an error is reported:
23
+ | linter | problem | location |
24
+ | ElementWithDuplicateTagsLinter | Scenario has duplicate tag '@same_tag'. | <path_to_file>:4 |
25
+
26
+
27
+ Scenario: Configuration of indirect tag inclusion (turned off)
28
+
29
+ Note: Tags inherited from other elements are not included by default
30
+
31
+ Given a linter for elements with duplicate tags has been registered
32
+ And the following configuration file:
33
+ """
34
+ ElementWithDuplicateTagsLinter:
35
+ IncludeInheritedTags: false
36
+ """
37
+ And the following feature:
38
+ """
39
+ @same_tag
40
+ Feature:
41
+
42
+ @same_tag
43
+ Scenario:
44
+ * a step
45
+ """
46
+ When the configuration file is loaded
47
+ And it is linted
48
+ Then no error is reported
49
+
50
+
51
+ Scenario: Configuration of indirect tag inclusion (turned on)
52
+ Given a linter for elements with duplicate tags has been registered
53
+ And the following configuration file:
54
+ """
55
+ ElementWithDuplicateTagsLinter:
56
+ IncludeInheritedTags: true
57
+ """
58
+ And the following feature:
59
+ """
60
+ @same_tag
61
+ Feature:
62
+
63
+ @same_tag
64
+ Scenario:
65
+ * a step
66
+ """
67
+ When the configuration file is loaded
68
+ And it is linted
69
+ Then an error is reported:
70
+ | linter | problem | location |
71
+ | ElementWithDuplicateTagsLinter | Scenario has duplicate tag '@same_tag'. | <path_to_file>:5 |
@@ -0,0 +1,32 @@
1
+ Feature: Feature file with mismatched name linter
2
+
3
+ As a reader of documentation
4
+ I want file names to match their features
5
+ so that I can tell what a file is about by reading the name
6
+
7
+ Scenario: Linting files with mismatched names
8
+ Given a feature file model based on the file "some_name" with the following text:
9
+ """
10
+ Feature: Some different name
11
+ """
12
+ And a linter for features with mismatched file names
13
+ When it is linted
14
+ Then an error is reported:
15
+ | linter | problem | location |
16
+ | FeatureFileWithMismatchedNameLinter | Feature file name does not match feature name. | <path_to_file> |
17
+
18
+ Scenario Outline: Linting files with matching names
19
+ Given a feature file model based on the file "<file name>" with the following text:
20
+ """
21
+ Feature: <feature name>
22
+ """
23
+ And a linter for features with mismatched file names
24
+ When it is linted
25
+ Then no error is reported
26
+
27
+ Examples:
28
+ | file name | feature name |
29
+ | name_with_underscores | Name with_underscores |
30
+ | name with spaces | Name with spaces |
31
+ | NameWithCaps | Name with Caps |
32
+ | name-with-hyphens | Name with-hyphens |