Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/custom linters #8

Merged
merged 51 commits into from
Aug 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
1fef014
Adding specs, .gitignore
johngluckmdsol Jun 13, 2017
f471dad
Added specs. last one is not working
nagarwal-mdsol Jun 13, 2017
bcd393c
Specs are working but they need some help
johngluckmdsol Jun 14, 2017
537525e
Making LINTER construction more dynamic
johngluckmdsol Jun 14, 2017
e8e6b34
Adding more specs
johngluckmdsol Jun 14, 2017
2fcb22c
Cleaning up linter
johngluckmdsol Jun 14, 2017
5e3146f
Checking in progress
johngluckmdsol Jun 14, 2017
2595854
rubocop
nagarwal-mdsol Jun 14, 2017
c816683
Committing progress
johngluckmdsol Jun 14, 2017
00b602b
specs
nagarwal-mdsol Jun 14, 2017
060a70f
Adding config/default.yml with all linters enabled
johngluckmdsol Jun 14, 2017
acfa0b2
bump version
johngluckmdsol Jun 14, 2017
438d0a3
Rubocopping
johngluckmdsol Jun 14, 2017
330bf08
Cleanup
johngluckmdsol Jun 14, 2017
14e715a
Rubocop
johngluckmdsol Jun 14, 2017
2620521
in progress
nagarwal-mdsol Jun 15, 2017
9cf82b7
Rubocop
johngluckmdsol Jun 15, 2017
b5df113
Added user config, required_tags feature
nagarwal-mdsol Jun 15, 2017
55f28a4
updated spec contexts
nagarwal-mdsol Jun 15, 2017
440fd88
Cleanup after feature run. Rubocopped one file
nagarwal-mdsol Jun 15, 2017
0150b1d
Rubocop
johngluckmdsol Jun 15, 2017
92611e2
rubocopped
johngluckmdsol Jun 15, 2017
472d2f5
Committing progress
johngluckmdsol Jun 16, 2017
2c24b72
Pushing progress, all tests pass
johngluckmdsol Jun 16, 2017
b7f5f8e
Progress, all tests pass
johngluckmdsol Jun 16, 2017
6f30b4a
Remove ARGV construct because it actually is broken on file expansion…
johngluckmdsol Jun 16, 2017
45fb6fa
fix command so it works as gem. Linting my own feature
johngluckmdsol Jun 16, 2017
7d41260
rubocopping
johngluckmdsol Jun 16, 2017
8c06c88
making default.yml single source of truth
nagarwal-mdsol Jun 19, 2017
25d8875
Make features pass by disabling all linters with a local file and cal…
johngluckmdsol Jun 19, 2017
4c7b491
Rubocopping
johngluckmdsol Jun 19, 2017
6d95015
Remove lock file
johngluckmdsol Jun 19, 2017
f151657
Fix feature to work with Before
johngluckmdsol Jun 19, 2017
c0611f5
rubocop
johngluckmdsol Jun 19, 2017
25bee7c
Rubocop is clean
johngluckmdsol Jun 19, 2017
368e857
Update README
johngluckmdsol Jun 19, 2017
a251416
We should not pass silently
johngluckmdsol Jun 19, 2017
3903a21
Revert verbose success. Not so easy
johngluckmdsol Jun 19, 2017
a0591c4
Updated docs to reflect changes
johngluckmdsol Jun 19, 2017
2785a07
Updated local config location, added break
nagarwal-mdsol Jun 21, 2017
e5a4e96
Correction to readme
johngluckmdsol Jun 21, 2017
6a49041
Typo in readme
johngluckmdsol Jun 21, 2017
3e52a27
Figured out verbose success
johngluckmdsol Jun 21, 2017
4e6c49a
Fix rubocop
johngluckmdsol Jun 21, 2017
abaa08e
Adding testing feature to clean up tests
johngluckmdsol Jul 10, 2017
c229bac
Removing state booleans
johngluckmdsol Jul 10, 2017
84842c8
Fix rubocop
johngluckmdsol Jul 11, 2017
d58eaa6
Making suggested corrections
johngluckmdsol Jul 17, 2017
9004908
Setting report call back to the way it was
johngluckmdsol Jul 17, 2017
5776647
Rubocop
johngluckmdsol Jul 18, 2017
a924023
Rubocop conf
johngluckmdsol Jul 18, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Gemfile.lock
.bundle
.idea
tmp
20 changes: 19 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ Metrics/ClassLength:
# URISchemes: http, https
Metrics/LineLength:
Max: 116

Exclude:
- "**/*_spec.rb"
# Offense count: 1
# Configuration parameters: CountComments.
Metrics/MethodLength:
Expand All @@ -33,3 +34,20 @@ Metrics/MethodLength:
Style/NumericPredicate:
Exclude:
- 'lib/gherkin_lint/linter/file_name_differs_feature_name.rb'

Metrics/ModuleLength:
Exclude:
- "**/*_spec.rb"

Metrics/BlockLength:
Exclude:
- "**/*_spec.rb"

Layout/IndentationWidth:
Exclude:
- "**/*_spec.rb"

Layout/IndentHeredoc:
Exclude:
- "**/*_spec.rb"

1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ gem 'gherkin', '>=4.0.0'
# TODO: update to gherkin4 gem 'gherkin_format'
# TODO: update to gherkin4 gem 'gherkin_language'
gem 'rake'
gem 'rspec'
gem 'rubocop'
gem 'term-ansicolor'
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ This tool lints gherkin files.

run `gherkin_lint` on a list of files

gherkin_lint FEATURE_FILES
gherkin_lint -f '<wild_card_path>' #default is `features/**/*.feature`

With `--disable CHECK` or `--enable CHECK` it's possible to disable respectivly enable program wide checks.
With `--disable CHECK` or `--enable CHECK` it's possible to disable respectivly enable program wide checks except when a linter requires additional values to be set in order to be valid. Currently only RequiredTagStartsWith meets this criteria.

Checks could be disabled using tags within Feature Files. To do so, add @disableCHECK.
Detailed usage within the [disable_tags](https://github.com/funkwerk/gherkin_lint/blob/master/features/disable_tags.feature) feature.
Expand Down Expand Up @@ -45,6 +45,7 @@ This will mount the current directory within the Gherkin Lint Docker Container a
- [missing scenario name](https://github.com/funkwerk/gherkin_lint/blob/master/features/missing_scenario_name.feature)
- [missing test action](https://github.com/funkwerk/gherkin_lint/blob/master/features/missing_test_action.feature)
- [missing verification](https://github.com/funkwerk/gherkin_lint/blob/master/features/missing_verification.feature)
- [required tag starts with](https://github.com/funkwerk/gherkin_lint/blob/master/features/required_tag_starts_with.feature) - disabled by default
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could this be more specific? I for example have an requirement that I want my tags match a regexp pattern. just allow a few, the others Tags should be valid ticket numbers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We thought about this and decided that there are several kinds of linters that could be implemented (StartsWith, ExactMatch, Regex, Includes) and rather than implement all of them, we implemented what was required for our project along with a Mixin that could be included to create all the others. But rather than try to have this one do everything, we decided to go with the Single Responsibility prinicple.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

- [same tag for all scenarios](https://github.com/funkwerk/gherkin_lint/blob/master/features/same_tag_for_all_scenarios.feature)
- [tag used multiple times](https://github.com/funkwerk/gherkin_lint/blob/master/features/tag_used_multiple_times.feature)
- [too clumsy](https://github.com/funkwerk/gherkin_lint/blob/master/features/too_clumsy.feature)
Expand Down Expand Up @@ -77,3 +78,6 @@ Install it with:
`sudo gem install gherkin_lint`

After that `gherkin_lint` executable is available.

## Configuration
If you have a custom configuration you'd like to run on a regular basis instead of passing enable and disable flags through the CLI on every run, you can configure a ```.gherkin_lint.yml``` file that will be loaded on execution. The format and available linters are in [```config/default.yml```](config/default.yml)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would like if there is a gherkin_lint --auto-gen-config similar to rubocop. Nobody knows where gherkin_lint is installed and where the config/default.yml is located. It is also difficult to Keep the config/default.yml up to date, when addind a new Feature. An generated config may handle this better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We took a look at this in rubocop and there is an lot of code that makes this work. We figured that this would be an acceptable shortcut for now. You don't have to have .gherkin_lint and the only people who need to know where the default is are gherkin_lint developers. I agree that there needs to be a better way to add new linters, but we didn't want to take that architectural liberty.

That said, I'll see if there is a quick and dirty way to solve this

Copy link
Contributor Author

@johngluckmdsol johngluckmdsol Jul 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So would adding a CLI option to specify a config file (defaulting to .gherkin_lint.yml) work for you? Auto-gen-config as implemented in rubocop would require quite a few more changes.

Copy link
Member

@lindt lindt Jul 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't checking if there is a .gherkin_lint.yml file enough? Then wouldn't need to CLI option. If there is no .gherkin_lint.yml-file, then the default linters are enabled with the default configuration.

Is it okay that if there is a .gherkin_lint.yml and for testing I want to disable a check, that the CLI options override the .gherkin_lint.yml settings?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote a feature file to demonstrate that this is working as you specified. Is this okay? We are already doing what you asked, I think. I just wrote a test to prove it.

4 changes: 2 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ task :language do
end

task :self_check do
disabled_checks = %w(
disabled_checks = %w[
UnknownVariable
BadScenarioName
)
]
sh "RUBYLIB=lib ./bin/gherkin_lint --disable #{disabled_checks.join ','} features/*.feature"
end
12 changes: 10 additions & 2 deletions bin/gherkin_lint
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,21 @@ OptionParser.new do |opts|
opts.on('--disable [CHECKS]', 'Disabled checks. Separated by ","') do |checks|
options[:disable] = checks.split(',')
end
opts.on('-f', '--filepath [file/s]', 'File path where features are located') do |file|
options[:files] = file
end
end.parse!

linter = GherkinLint::GherkinLint.new

linter.disable options[:disable] if options.key? :disable
linter.enable options[:enable] if options.key? :enable
linter.set_linter

options[:files] = 'features/**/*.feature' if options[:files].nil?
files = Dir.glob(options[:files])

ARGV.each { |file| linter.analyze file }
files.each do |file|
linter.analyze file
end

exit linter.report
58 changes: 58 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
AvoidOutlineForSingleExample:
Enabled: true
AvoidPeriod:
Enabled: true
AvoidScripting:
Enabled: true
BackgroundDoesMoreThanSetup:
Enabled: true
BackgroundRequiresMultipleScenarios:
Enabled: true
BadScenarioName:
Enabled: true
BeDeclarative:
Enabled: true
FileNameDiffersFeatureName:
Enabled: true
MissingExampleName:
Enabled: true
MissingFeatureDescription:
Enabled: true
MissingFeatureName:
Enabled: true
MissingScenarioName:
Enabled: true
MissingTestAction:
Enabled: true
MissingVerification:
Enabled: true
InvalidFileName:
Enabled: true
InvalidStepFlow:
Enabled: true
RequiredTagsStartsWith:
Enabled: false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it is a regexp, it could be enabled everytime. so just set it to match everything as Default.

Copy link
Contributor Author

@johngluckmdsol johngluckmdsol Jul 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above comment. The idea is that there are multiple types of TagConstraint linters so it didn't make sense to always have an enabled default since, at some point, those linters would easily conflict with each other.

SameTagForAllScenarios:
Enabled: true
TagUsedMultipleTimes:
Enabled: true
TooClumsy:
Enabled: true
TooManyDifferentTags:
Enabled: true
TooManySteps:
Enabled: true
TooManyTags:
Enabled: true
TooLongStep:
Enabled: true
UniqueScenarioNames:
Enabled: true
UnknownVariable:
Enabled: true
UnusedVariable:
Enabled: true
UseBackground:
Enabled: true
UseOutline:
Enabled: true
3 changes: 2 additions & 1 deletion features/avoid_outline_for_single_example.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ Feature: Avoid Outline for single Example
so that it's easier to reuse verification steps

Background: Prepare Testee

Given a file named "lint.rb" with:
"""
$LOAD_PATH << '../../lib'
require 'gherkin_lint'

linter = GherkinLint::GherkinLint.new
linter.enable %w(AvoidOutlineForSingleExample)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -52,5 +54,4 @@ Feature: Avoid Outline for single Example
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
2 changes: 1 addition & 1 deletion features/avoid_period.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: Avoid Period

linter = GherkinLint::GherkinLint.new
linter.enable %w(AvoidPeriod)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -45,5 +46,4 @@ Feature: Avoid Period
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
2 changes: 1 addition & 1 deletion features/avoid_scripting.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: Avoid Scripting

linter = GherkinLint::GherkinLint.new
linter.enable %w(AvoidScripting)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -65,5 +66,4 @@ Feature: Avoid Scripting
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
2 changes: 1 addition & 1 deletion features/background_does_more_than_setup.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: Background Does More Than Setup

linter = GherkinLint::GherkinLint.new
linter.enable %w(BackgroundDoesMoreThanSetup)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -42,5 +43,4 @@ Feature: Background Does More Than Setup
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
2 changes: 1 addition & 1 deletion features/background_requires_scenario.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: Background Requires Scenario

linter = GherkinLint::GherkinLint.new
linter.enable %w(BackgroundRequiresMultipleScenarios)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -53,5 +54,4 @@ Feature: Background Requires Scenario
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
2 changes: 1 addition & 1 deletion features/bad_scenario_name.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: Bad Scenario Name

linter = GherkinLint::GherkinLint.new
linter.enable %w(BadScenarioName)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -49,5 +50,4 @@ Feature: Bad Scenario Name
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
2 changes: 1 addition & 1 deletion features/be_declarative.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: Be Declarative

linter = GherkinLint::GherkinLint.new
linter.enable %w(BeDeclarative)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -49,5 +50,4 @@ Feature: Be Declarative
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
3 changes: 1 addition & 2 deletions features/disable_tags.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: Disable Tags

linter = GherkinLint::GherkinLint.new
linter.enable %w(InvalidStepFlow)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -54,7 +55,6 @@ Feature: Disable Tags
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""

Scenario: Disable on Feature Level
Expand All @@ -73,5 +73,4 @@ Feature: Disable Tags
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
4 changes: 2 additions & 2 deletions features/file_name_differs_feature_name.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: File Name Differs Feature Name

linter = GherkinLint::GherkinLint.new
linter.enable %w(FileNameDiffersFeatureName)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand All @@ -37,7 +38,6 @@ Feature: File Name Differs Feature Name
When I run `ruby lint.rb lint.feature`
Then it should pass with exactly:
"""

"""

Examples: Valid Names
Expand All @@ -54,6 +54,7 @@ Feature: File Name Differs Feature Name

linter = GherkinLint::GherkinLint.new
linter.enable %w(FileNameDiffersFeatureName)
linter.set_linter
linter.analyze 'lint_test.feature'
exit linter.report

Expand All @@ -65,7 +66,6 @@ Feature: File Name Differs Feature Name
When I run `ruby lint.rb lint_test.feature`
Then it should pass with exactly:
"""

"""

Examples: Valid Names
Expand Down
2 changes: 1 addition & 1 deletion features/invalid_file_name.feature
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Feature: Invalid File Name

linter = GherkinLint::GherkinLint.new
linter.enable %w(InvalidFileName)
linter.set_linter
ARGV.each { |file| linter.analyze file }
exit linter.report

Expand Down Expand Up @@ -46,5 +47,4 @@ Feature: Invalid File Name
When I run `ruby lint.rb lint.feature`
Then it should pass with exactly:
"""

"""
2 changes: 1 addition & 1 deletion features/invalid_step_flow.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: Invalid Step Flow

linter = GherkinLint::GherkinLint.new
linter.enable %w(InvalidStepFlow)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -81,5 +82,4 @@ Feature: Invalid Step Flow
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
3 changes: 1 addition & 2 deletions features/missing_example_name.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: Missing Example Name

linter = GherkinLint::GherkinLint.new
linter.enable %w(MissingExampleName)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -57,7 +58,6 @@ Feature: Missing Example Name
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""

Scenario: Valid Example
Expand All @@ -83,5 +83,4 @@ Feature: Missing Example Name
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
2 changes: 1 addition & 1 deletion features/missing_feature_description.feature
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Feature: Missing Feature Description

linter = GherkinLint::GherkinLint.new
linter.enable %w(MissingFeatureDescription)
linter.set_linter
linter.analyze 'lint.feature'
exit linter.report

Expand Down Expand Up @@ -40,5 +41,4 @@ Feature: Missing Feature Description
When I run `ruby lint.rb`
Then it should pass with exactly:
"""

"""
Loading