cuke_linter 0.2.0 → 0.3.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/CHANGELOG.md +7 -1
- data/Rakefile +21 -6
- data/cuke_linter.gemspec +1 -1
- data/environments/cucumber_env.rb +8 -0
- data/environments/rspec_env.rb +2 -0
- data/lib/cuke_linter.rb +32 -9
- data/lib/cuke_linter/linters/test_with_too_many_steps_linter.rb +9 -3
- data/lib/cuke_linter/version.rb +1 -1
- data/testing/cucumber/features/configuration/configuring_linters.feature +19 -0
- data/testing/cucumber/features/configuration/using_configurations.feature +46 -0
- data/testing/cucumber/features/linters/default_linters.feature +1 -1
- data/testing/cucumber/features/linters/test_with_too_many_steps.feature +23 -0
- data/testing/cucumber/step_definitions/action_steps.rb +24 -4
- data/testing/cucumber/step_definitions/setup_steps.rb +24 -2
- data/testing/cucumber/step_definitions/verification_steps.rb +8 -0
- data/testing/file_helper.rb +12 -0
- data/testing/linter_factory.rb +9 -3
- data/testing/rspec/spec/integration/cuke_linter_integration_spec.rb +75 -0
- data/testing/rspec/spec/unit/cuke_linter_unit_spec.rb +18 -0
- data/testing/rspec/spec/unit/linters/configurable_linter_unit_specs.rb +11 -0
- data/testing/rspec/spec/unit/linters/test_with_too_many_steps_linter_unit_spec.rb +73 -0
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bc43845a692a99b982b4a41b56c877bc41231bf931e04defd9d70aad2193f04
|
4
|
+
data.tar.gz: 6b8e365c8eda00b38728d02fd88caad4b04fc601c94caeb03dc760bc374ebac9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 650f8900dc73461011250fc3d487c0c14f85e7064c7bed6b65316fedaeac167dd368127ee900774058d6109e6a4ea397994eeeffa9b6295fec223ae5c5344cf4
|
7
|
+
data.tar.gz: 9ee27f5bc99953d7b830dd4ffcdec2fd47b6fe51f1b4f9fce2cdb1380495705325fa10be710afdf88268c1c4113a36803e8a71bcc5c1d1932749c0784f151bc2
|
data/CHANGELOG.md
CHANGED
@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
8
8
|
|
9
9
|
Nothing yet...
|
10
10
|
|
11
|
+
## [0.3.0] - 2019-04-07
|
12
|
+
|
13
|
+
### Added
|
14
|
+
- Linter configuration: linters can now be configured (turned on/off, conditions changed, etc.) instead of having to always use the default settings
|
15
|
+
|
11
16
|
## [0.2.0] - 2019-03-19
|
12
17
|
|
13
18
|
### Added
|
@@ -23,6 +28,7 @@ Nothing yet...
|
|
23
28
|
- Custom linters, formatters, and command line usability
|
24
29
|
|
25
30
|
|
26
|
-
[Unreleased]: https://github.com/enkessler/cuke_linter/compare/v0.
|
31
|
+
[Unreleased]: https://github.com/enkessler/cuke_linter/compare/v0.3.0...HEAD
|
32
|
+
[0.3.0]: https://github.com/enkessler/cuke_linter/compare/v0.2.0...v0.3.0
|
27
33
|
[0.2.0]: https://github.com/enkessler/cuke_linter/compare/v0.1.0...v0.2.0
|
28
34
|
[0.1.0]: https://github.com/enkessler/cuke_linter/compare/2bbd3f29f4eb45b6e9ea7d47c5bb47182bf4fde7...v0.1.0
|
data/Rakefile
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'racatt'
|
3
3
|
require 'coveralls/rake/task'
|
4
|
-
require '
|
4
|
+
require 'rainbow'
|
5
5
|
|
6
|
+
Rainbow.enabled = true
|
6
7
|
|
7
8
|
namespace 'racatt' do
|
8
9
|
Racatt.create_tasks
|
@@ -19,20 +20,20 @@ namespace 'cuke_linter' do
|
|
19
20
|
|
20
21
|
desc 'Check documentation with RDoc'
|
21
22
|
task :check_documentation do
|
22
|
-
output = `rdoc lib`
|
23
|
+
output = `rdoc lib -C`
|
23
24
|
puts output
|
24
25
|
|
25
26
|
if output =~ /100.00% documented/
|
26
|
-
puts 'All code documented'.green
|
27
|
+
puts Rainbow('All code documented').green
|
27
28
|
else
|
28
|
-
raise 'Parts of the gem are undocumented'.red
|
29
|
+
raise Rainbow('Parts of the gem are undocumented').red
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
33
|
desc 'Run all of the tests'
|
33
34
|
task :test_everything => [:clear_coverage] do
|
34
|
-
rspec_args = '--pattern "testing/rspec/spec/**/*_spec.rb"'
|
35
|
-
cucumber_args = "testing/cucumber/features -r environments/cucumber_env.rb -f progress -t 'not @wip'"
|
35
|
+
rspec_args = '--pattern "testing/rspec/spec/**/*_spec.rb" --force-color'
|
36
|
+
cucumber_args = "testing/cucumber/features -r environments/cucumber_env.rb -f progress -t 'not @wip' --color"
|
36
37
|
|
37
38
|
Rake::Task['racatt:test_everything'].invoke(rspec_args, cucumber_args)
|
38
39
|
end
|
@@ -42,6 +43,20 @@ namespace 'cuke_linter' do
|
|
42
43
|
|
43
44
|
desc 'The task that CI will run. Do not run locally.'
|
44
45
|
task :ci_build => ['cuke_linter:test_everything', 'coveralls:push']
|
46
|
+
|
47
|
+
desc 'Check that things look good before trying to release'
|
48
|
+
task :prerelease_check do
|
49
|
+
begin
|
50
|
+
Rake::Task['cuke_linter:test_everything'].invoke
|
51
|
+
Rake::Task['cuke_linter:check_documentation'].invoke
|
52
|
+
rescue => e
|
53
|
+
puts Rainbow("Something isn't right!").red
|
54
|
+
raise e
|
55
|
+
end
|
56
|
+
|
57
|
+
puts Rainbow('All is well. :)').green
|
58
|
+
end
|
59
|
+
|
45
60
|
end
|
46
61
|
|
47
62
|
|
data/cuke_linter.gemspec
CHANGED
@@ -33,5 +33,5 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency "rspec", "~> 3.0"
|
34
34
|
spec.add_development_dependency 'simplecov', '< 1.0.0'
|
35
35
|
spec.add_development_dependency 'coveralls', '< 1.0.0'
|
36
|
-
spec.add_development_dependency '
|
36
|
+
spec.add_development_dependency 'rainbow', '< 4.0.0'
|
37
37
|
end
|
@@ -7,6 +7,14 @@ require 'cucumber'
|
|
7
7
|
require_all 'testing/cucumber/step_definitions'
|
8
8
|
|
9
9
|
|
10
|
+
Before do
|
11
|
+
CukeLinter.clear_registered_linters
|
12
|
+
end
|
13
|
+
|
14
|
+
Before do
|
15
|
+
@root_test_directory = CukeLinter::FileHelper.create_directory
|
16
|
+
end
|
17
|
+
|
10
18
|
at_exit do
|
11
19
|
CukeLinter::FileHelper.created_directories.each do |dir_path|
|
12
20
|
FileUtils.remove_entry(dir_path, true)
|
data/environments/rspec_env.rb
CHANGED
@@ -4,8 +4,10 @@ SimpleCov.command_name('rspec_tests')
|
|
4
4
|
require_relative 'common_env'
|
5
5
|
require 'rspec'
|
6
6
|
require 'rubygems/mock_gem_ui'
|
7
|
+
require 'yaml'
|
7
8
|
|
8
9
|
require_relative '../testing/rspec/spec/unit/formatters/formatter_unit_specs'
|
10
|
+
require_relative '../testing/rspec/spec/unit/linters/configurable_linter_unit_specs'
|
9
11
|
require_relative '../testing/rspec/spec/unit/linters/linter_unit_specs'
|
10
12
|
require_relative '../testing/rspec/spec/integration/formatters/formatter_integration_specs'
|
11
13
|
require_relative '../testing/rspec/spec/integration/linters/linter_integration_specs'
|
data/lib/cuke_linter.rb
CHANGED
@@ -12,33 +12,56 @@ require 'cuke_linter/linters/test_with_too_many_steps_linter'
|
|
12
12
|
|
13
13
|
module CukeLinter
|
14
14
|
|
15
|
-
@
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
@original_linters = { 'FeatureWithoutScenariosLinter' => FeatureWithoutScenariosLinter.new,
|
16
|
+
'ExampleWithoutNameLinter' => ExampleWithoutNameLinter.new,
|
17
|
+
'OutlineWithSingleExampleRowLinter' => OutlineWithSingleExampleRowLinter.new,
|
18
|
+
'TestWithTooManyStepsLinter' => TestWithTooManyStepsLinter.new }
|
19
|
+
|
20
|
+
# Configures linters based on the given options
|
21
|
+
def self.load_configuration(config_file_path: nil, config: nil)
|
22
|
+
# TODO: define what happens if both a configuration file and a configuration are provided. Merge them or have direct config take precedence? Both?
|
23
|
+
|
24
|
+
unless config || config_file_path
|
25
|
+
config_file_path = "#{Dir.pwd}/.cuke_linter"
|
26
|
+
raise 'No configuration or configuration file given and no .cuke_linter file found' unless File.exist?(config_file_path)
|
27
|
+
end
|
28
|
+
|
29
|
+
config = config || YAML.load_file(config_file_path)
|
30
|
+
|
31
|
+
config.each_pair do |linter_name, options|
|
32
|
+
unregister_linter(linter_name) if options.key?('Enabled') && !options['Enabled']
|
33
|
+
|
34
|
+
registered_linters[linter_name].configure(options) if registered_linters[linter_name]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns the registered linters to their default state
|
39
|
+
def self.reset_linters
|
40
|
+
@registered_linters = nil
|
41
|
+
end
|
19
42
|
|
20
43
|
# Registers for linting use the given linter object, tracked by the given name
|
21
44
|
def self.register_linter(linter:, name:)
|
22
|
-
|
45
|
+
self.registered_linters[name] = linter
|
23
46
|
end
|
24
47
|
|
25
48
|
# Unregisters the linter object tracked by the given name so that it is not used for linting
|
26
49
|
def self.unregister_linter(name)
|
27
|
-
|
50
|
+
self.registered_linters.delete(name)
|
28
51
|
end
|
29
52
|
|
30
53
|
# Lists the names of the currently registered linting objects
|
31
54
|
def self.registered_linters
|
32
|
-
@registered_linters
|
55
|
+
@registered_linters ||= Marshal.load(Marshal.dump(@original_linters))
|
33
56
|
end
|
34
57
|
|
35
58
|
# Unregisters all currently registered linting objects
|
36
59
|
def self.clear_registered_linters
|
37
|
-
|
60
|
+
self.registered_linters.clear
|
38
61
|
end
|
39
62
|
|
40
63
|
# Lints the tree of model objects rooted at the given model using the given linting objects and formatting the results with the given formatters and their respective output locations
|
41
|
-
def self.lint(model_tree: CukeModeler::Directory.new(Dir.pwd), linters:
|
64
|
+
def self.lint(model_tree: CukeModeler::Directory.new(Dir.pwd), linters: self.registered_linters.values, formatters: [[CukeLinter::PrettyFormatter.new]])
|
42
65
|
# puts "model tree: #{model_tree}"
|
43
66
|
# puts "linters: #{linters}"
|
44
67
|
# puts "formatters: #{formatters}"
|
@@ -9,14 +9,20 @@ module CukeLinter
|
|
9
9
|
'TestWithTooManyStepsLinter'
|
10
10
|
end
|
11
11
|
|
12
|
+
# Changes the linting settings on the linter using the provided configuration
|
13
|
+
def configure(options)
|
14
|
+
@step_threshold = options['StepThreshold'] if options['StepThreshold']
|
15
|
+
end
|
16
|
+
|
12
17
|
# Lints the given model and returns linting data about said model
|
13
18
|
def lint(model)
|
14
19
|
return [] unless model.is_a?(CukeModeler::Scenario) || model.is_a?(CukeModeler::Outline)
|
15
20
|
|
16
|
-
step_count
|
21
|
+
step_count = model.steps.nil? ? 0 : model.steps.count
|
22
|
+
step_threshold = @step_threshold || 10
|
17
23
|
|
18
|
-
if step_count >
|
19
|
-
[{ problem: "Test has too many steps. #{step_count} steps found (max
|
24
|
+
if step_count > step_threshold
|
25
|
+
[{ problem: "Test has too many steps. #{step_count} steps found (max #{step_threshold})", location: "#{model.get_ancestor(:feature_file).path}:#{model.source_line}" }]
|
20
26
|
else
|
21
27
|
[]
|
22
28
|
end
|
data/lib/cuke_linter/version.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: Configuration of linters
|
2
|
+
|
3
|
+
Instead of having to modify the linting object directly in a script at runtime, a configuration file can be used so that specific linters can be configured in a more convenient, static manner. Some configurable properties are available across all linters while some are linter specific.
|
4
|
+
|
5
|
+
|
6
|
+
Scenario: Disabling a linter
|
7
|
+
Given a linter registered as "AlwaysFindsAProblem"
|
8
|
+
And the following configuration file:
|
9
|
+
"""
|
10
|
+
AlwaysFindsAProblem:
|
11
|
+
Enabled: false
|
12
|
+
"""
|
13
|
+
And the following feature:
|
14
|
+
"""
|
15
|
+
Feature: Something in which a problem could exist
|
16
|
+
"""
|
17
|
+
When the configuration file is used
|
18
|
+
And the feature is linted
|
19
|
+
Then no error is reported
|
@@ -0,0 +1,46 @@
|
|
1
|
+
Feature: Using a configuration
|
2
|
+
|
3
|
+
Configuration can be done during a script or through a configuration file. This file can be explicitly provided or a default configuration file will be used.
|
4
|
+
|
5
|
+
|
6
|
+
Scenario: Providing a configuration directly
|
7
|
+
Given a linter registered as "SomeLinter"
|
8
|
+
When the following code is used:
|
9
|
+
"""
|
10
|
+
CukeLinter.load_configuration(config: { 'SomeLinter' => { 'Enabled' => false } })
|
11
|
+
"""
|
12
|
+
Then the linter "SomeLinter" is no longer registered
|
13
|
+
|
14
|
+
Scenario: Loading a configuration from a file
|
15
|
+
Given a linter registered as "SomeLinter"
|
16
|
+
And the following configuration file "my_config.file":
|
17
|
+
"""
|
18
|
+
SomeLinter:
|
19
|
+
Enabled: false
|
20
|
+
"""
|
21
|
+
When the following code is used:
|
22
|
+
"""
|
23
|
+
CukeLinter.load_configuration(config_file_path: '<path_to>/my_config.file')
|
24
|
+
"""
|
25
|
+
Then the linter "SomeLinter" is no longer registered
|
26
|
+
|
27
|
+
Scenario: Using the default configuration file
|
28
|
+
Given a directory "test_directory"
|
29
|
+
And the following configuration file "test_directory/.cuke_linter":
|
30
|
+
"""
|
31
|
+
SomeLinter:
|
32
|
+
Enabled: false
|
33
|
+
"""
|
34
|
+
And a linter registered as "SomeLinter"
|
35
|
+
When "test_directory" is the current directory
|
36
|
+
And the following code is used:
|
37
|
+
"""
|
38
|
+
CukeLinter.load_configuration
|
39
|
+
"""
|
40
|
+
Then the linter "SomeLinter" is no longer registered
|
41
|
+
|
42
|
+
@wip
|
43
|
+
Scenario: Configuring from the command line
|
44
|
+
|
45
|
+
@wip
|
46
|
+
Scenario: Using the default configuration file from the command line
|
@@ -6,7 +6,7 @@ Feature: Default Linters
|
|
6
6
|
|
7
7
|
|
8
8
|
Scenario: Using the default linters
|
9
|
-
Given no other linters have been registered
|
9
|
+
Given no other linters have been registered or unregistered
|
10
10
|
Then the following linters are registered by default
|
11
11
|
| ExampleWithoutNameLinter |
|
12
12
|
| FeatureWithoutScenariosLinter |
|
@@ -31,3 +31,26 @@ Feature: Test with too many steps linter
|
|
31
31
|
Then an error is reported
|
32
32
|
| linter | problem | location |
|
33
33
|
| TestWithTooManyStepsLinter | Test has too many steps. 11 steps found (max 10) | <path_to_file>:3 |
|
34
|
+
|
35
|
+
Scenario: Configuration of step count threshold
|
36
|
+
Given a linter for tests with too many steps has been registered
|
37
|
+
And the following configuration file:
|
38
|
+
"""
|
39
|
+
TestWithTooManyStepsLinter:
|
40
|
+
StepThreshold: 3
|
41
|
+
"""
|
42
|
+
And the following feature:
|
43
|
+
"""
|
44
|
+
Feature:
|
45
|
+
|
46
|
+
Scenario:
|
47
|
+
* step 1
|
48
|
+
* step 2
|
49
|
+
* step 3
|
50
|
+
* step one too many...
|
51
|
+
"""
|
52
|
+
When the configuration file is loaded
|
53
|
+
And the feature is linted
|
54
|
+
Then an error is reported
|
55
|
+
| linter | problem | location |
|
56
|
+
| TestWithTooManyStepsLinter | Test has too many steps. 4 steps found (max 3) | <path_to_file>:3 |
|
@@ -8,10 +8,30 @@ When(/^it is formatted by the "([^"]*)" formatter$/) do |linter_name|
|
|
8
8
|
@results = CukeLinter.const_get("#{linter_name.capitalize}Formatter").new.format(@linter_data)
|
9
9
|
end
|
10
10
|
|
11
|
-
When(/^it is linted$/) do
|
12
|
-
options
|
13
|
-
|
14
|
-
|
11
|
+
When(/^(?:the feature|it) is linted$/) do
|
12
|
+
options = { model_tree: @model,
|
13
|
+
formatters: [[CukeLinter::FormatterFactory.generate_fake_formatter, "#{CukeLinter::FileHelper::create_directory}/junk_output_file.txt"]] }
|
14
|
+
options[:linters] = [@linter] if @linter
|
15
15
|
|
16
16
|
@results = CukeLinter.lint(options)
|
17
17
|
end
|
18
|
+
|
19
|
+
When(/^the configuration file is (?:used|loaded)$/) do
|
20
|
+
CukeLinter.load_configuration(config_file_path: @configuration_file_path)
|
21
|
+
end
|
22
|
+
|
23
|
+
And(/^the following code is used:$/) do |code|
|
24
|
+
code.sub!('<path_to>', @root_test_directory)
|
25
|
+
|
26
|
+
if @working_directory
|
27
|
+
Dir.chdir(@working_directory) do
|
28
|
+
eval(code)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
eval(code)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
When(/^"([^"]*)" is the current directory$/) do |directory|
|
36
|
+
@working_directory = "#{@root_test_directory}/#{directory}"
|
37
|
+
end
|
@@ -25,8 +25,8 @@ Given(/^a linter for features without scenarios$/) do
|
|
25
25
|
@linter = CukeLinter::FeatureWithoutScenariosLinter.new
|
26
26
|
end
|
27
27
|
|
28
|
-
Given(/^no other linters have been registered$/) do
|
29
|
-
|
28
|
+
Given(/^no other linters have been registered or unregistered$/) do
|
29
|
+
CukeLinter.reset_linters
|
30
30
|
end
|
31
31
|
|
32
32
|
Given(/^a linter for examples without names$/) do
|
@@ -40,3 +40,25 @@ end
|
|
40
40
|
Given(/^a linter for tests with too many steps$/) do
|
41
41
|
@linter = CukeLinter::TestWithTooManyStepsLinter.new
|
42
42
|
end
|
43
|
+
|
44
|
+
Given(/^a linter for tests with too many steps has been registered$/) do
|
45
|
+
CukeLinter.register_linter(linter: CukeLinter::TestWithTooManyStepsLinter.new, name: 'TestWithTooManyStepsLinter')
|
46
|
+
end
|
47
|
+
|
48
|
+
Given(/^the following configuration file(?: "([^"]*)")?:$/) do |file_name, text|
|
49
|
+
file_name ||= '.cuke_linter'
|
50
|
+
|
51
|
+
@configuration_file_path = CukeLinter::FileHelper.create_file(directory: @root_test_directory, name: file_name, extension: '', text: text)
|
52
|
+
end
|
53
|
+
|
54
|
+
Given(/^a linter "([^"]*)"$/) do |linter_class|
|
55
|
+
@linter = CukeLinter.const_get(linter_class).new
|
56
|
+
end
|
57
|
+
|
58
|
+
Given(/^a linter registered as "([^"]*)"$/) do |linter_name|
|
59
|
+
CukeLinter.register_linter(linter: CukeLinter::LinterFactory.generate_fake_linter(name: linter_name), name: linter_name)
|
60
|
+
end
|
61
|
+
|
62
|
+
Given(/^a directory "([^"]*)"$/) do |directory_name|
|
63
|
+
@test_directory = CukeLinter::FileHelper.create_directory(directory: @root_test_directory, name: directory_name)
|
64
|
+
end
|
@@ -17,3 +17,11 @@ end
|
|
17
17
|
Then(/^the following linters are registered by default$/) do |linter_names|
|
18
18
|
expect(CukeLinter.registered_linters.keys).to match_array(linter_names.raw.flatten)
|
19
19
|
end
|
20
|
+
|
21
|
+
Then(/^no error is reported$/) do
|
22
|
+
expect(@results).to be_empty
|
23
|
+
end
|
24
|
+
|
25
|
+
Then(/^the linter "([^"]*)" is no longer registered$/) do |linter_name|
|
26
|
+
expect(CukeLinter.registered_linters).to_not have_key(linter_name)
|
27
|
+
end
|
data/testing/file_helper.rb
CHANGED
@@ -22,6 +22,18 @@ module CukeLinter
|
|
22
22
|
path
|
23
23
|
end
|
24
24
|
|
25
|
+
def create_file(options = {})
|
26
|
+
options[:text] ||= ''
|
27
|
+
options[:name] ||= 'test_file'
|
28
|
+
options[:extension] ||= '.txt'
|
29
|
+
options[:directory] ||= create_directory
|
30
|
+
|
31
|
+
file_path = "#{options[:directory]}/#{options[:name]}#{options[:extension]}"
|
32
|
+
File.write(file_path, options[:text])
|
33
|
+
|
34
|
+
file_path
|
35
|
+
end
|
36
|
+
|
25
37
|
end
|
26
38
|
|
27
39
|
end
|
data/testing/linter_factory.rb
CHANGED
@@ -5,9 +5,10 @@ module CukeLinter
|
|
5
5
|
linter = Object.new
|
6
6
|
|
7
7
|
linter.define_singleton_method('lint') do |model|
|
8
|
-
location = model.respond_to?(:source_line) ? "#{model.get_ancestor(:feature_file).path}:#{model.source_line}" :
|
9
|
-
|
10
|
-
|
8
|
+
location = model.respond_to?(:source_line) ? "#{model.get_ancestor(:feature_file).path}:#{model.source_line}" : model.path
|
9
|
+
problem = @problem || "#{name} problem"
|
10
|
+
|
11
|
+
[{ problem: problem,
|
11
12
|
location: location }]
|
12
13
|
end
|
13
14
|
|
@@ -15,6 +16,11 @@ module CukeLinter
|
|
15
16
|
name
|
16
17
|
end
|
17
18
|
|
19
|
+
linter.define_singleton_method('configure') do |options|
|
20
|
+
@problem = options['Problem'] if options['Problem']
|
21
|
+
end
|
22
|
+
|
23
|
+
|
18
24
|
linter
|
19
25
|
end
|
20
26
|
|
@@ -115,4 +115,79 @@ RSpec.describe CukeLinter do
|
|
115
115
|
expect(subject.registered_linters['TestWithTooManyStepsLinter']).to be_a(CukeLinter::TestWithTooManyStepsLinter)
|
116
116
|
end
|
117
117
|
|
118
|
+
it 'returns to its default set of linters after being reset' do
|
119
|
+
original_names = CukeLinter.registered_linters.keys
|
120
|
+
original_linter_types = CukeLinter.registered_linters.values.map(&:class)
|
121
|
+
new_linter = CukeLinter::LinterFactory.generate_fake_linter
|
122
|
+
|
123
|
+
CukeLinter.register_linter(linter: new_linter, name: 'FakeLinter')
|
124
|
+
CukeLinter.reset_linters
|
125
|
+
|
126
|
+
expect(CukeLinter.registered_linters.keys).to eq(original_names)
|
127
|
+
expect(CukeLinter.registered_linters.values.map(&:class)).to eq(original_linter_types)
|
128
|
+
end
|
129
|
+
|
130
|
+
# To protect against someone modifying them
|
131
|
+
it 'does not reuse the old linting objects when resetting to the default linters' do
|
132
|
+
original_linter_ids = CukeLinter.registered_linters.values.map(&:object_id)
|
133
|
+
|
134
|
+
CukeLinter.reset_linters
|
135
|
+
|
136
|
+
expect(CukeLinter.registered_linters.values.map(&:object_id)).to_not match_array(original_linter_ids)
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
describe 'configuration' do
|
141
|
+
|
142
|
+
it 'unregisters disabled linters' do
|
143
|
+
config = { 'FakeLinter1' => { 'Enabled' => false } }
|
144
|
+
configuration_file = CukeLinter::FileHelper.create_file(name: '.cuke_linter', extension: '', text: config.to_yaml)
|
145
|
+
|
146
|
+
CukeLinter.register_linter(linter: CukeLinter::LinterFactory.generate_fake_linter(name: 'FakeLinter1'), name: 'FakeLinter1')
|
147
|
+
expect(subject.registered_linters['FakeLinter1']).to_not be nil
|
148
|
+
|
149
|
+
subject.load_configuration(config_file_path: configuration_file)
|
150
|
+
|
151
|
+
expect(subject.registered_linters['FakeLinter1']).to be nil
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'uses the default configuration file in the current directory if no configuration file is provided' do
|
155
|
+
config = { 'FakeLinter1' => { 'Enabled' => false } }
|
156
|
+
configuration_file = CukeLinter::FileHelper.create_file(name: '.cuke_linter', extension: '', text: config.to_yaml)
|
157
|
+
|
158
|
+
CukeLinter.register_linter(linter: CukeLinter::LinterFactory.generate_fake_linter(name: 'FakeLinter1'), name: 'FakeLinter1')
|
159
|
+
expect(subject.registered_linters['FakeLinter1']).to_not be nil
|
160
|
+
|
161
|
+
Dir.chdir(File.dirname(configuration_file)) do
|
162
|
+
subject.load_configuration
|
163
|
+
end
|
164
|
+
|
165
|
+
expect(subject.registered_linters['FakeLinter1']).to be nil
|
166
|
+
end
|
167
|
+
|
168
|
+
it 'raises an exception if no default configuration file is found and no configuration or file is provided' do
|
169
|
+
some_empty_directory = CukeLinter::FileHelper.create_directory
|
170
|
+
|
171
|
+
Dir.chdir(File.dirname(some_empty_directory)) do
|
172
|
+
expect { subject.load_configuration }.to raise_error('No configuration or configuration file given and no .cuke_linter file found')
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'configures every linter for which it has a configuration' do
|
177
|
+
config = { 'FakeLinter1' => { 'Problem' => 'My custom message for FakeLinter1' },
|
178
|
+
'FakeLinter2' => { 'Problem' => 'My custom message for FakeLinter2' } }
|
179
|
+
|
180
|
+
CukeLinter.register_linter(linter: CukeLinter::LinterFactory.generate_fake_linter(name: 'FakeLinter1'), name: 'FakeLinter1')
|
181
|
+
CukeLinter.register_linter(linter: CukeLinter::LinterFactory.generate_fake_linter(name: 'FakeLinter2'), name: 'FakeLinter2')
|
182
|
+
linting_options.delete(:linters)
|
183
|
+
|
184
|
+
subject.load_configuration(config: config)
|
185
|
+
results = subject.lint(linting_options)
|
186
|
+
|
187
|
+
expect(results).to match_array([{ linter: 'FakeLinter1', location: 'path_to_file:1', problem: 'My custom message for FakeLinter1' },
|
188
|
+
{ linter: 'FakeLinter2', location: 'path_to_file:1', problem: 'My custom message for FakeLinter2' }])
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
|
118
193
|
end
|
@@ -80,4 +80,22 @@ RSpec.describe CukeLinter do
|
|
80
80
|
expect(CukeLinter.registered_linters).to eq({})
|
81
81
|
end
|
82
82
|
|
83
|
+
it 'can reset to its default set of linters' do
|
84
|
+
expect(CukeLinter).to respond_to(:reset_linters)
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'configuration' do
|
88
|
+
|
89
|
+
it 'can load a configuration' do
|
90
|
+
expect(CukeLinter).to respond_to(:load_configuration)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'is configured optionally via a file or a directly provided configuration' do
|
94
|
+
expect(CukeLinter.method(:load_configuration).arity).to eq(-1)
|
95
|
+
expect(CukeLinter.method(:load_configuration).parameters).to match_array([[:key, :config_file_path],
|
96
|
+
[:key, :config]])
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
83
101
|
end
|
@@ -29,6 +29,7 @@ RSpec.describe CukeLinter::TestWithTooManyStepsLinter do
|
|
29
29
|
|
30
30
|
|
31
31
|
it_should_behave_like 'a linter at the unit level'
|
32
|
+
it_should_behave_like 'a configurable linter at the unit level'
|
32
33
|
|
33
34
|
|
34
35
|
it 'has a name' do
|
@@ -139,6 +140,78 @@ RSpec.describe CukeLinter::TestWithTooManyStepsLinter do
|
|
139
140
|
|
140
141
|
end
|
141
142
|
|
143
|
+
|
144
|
+
describe 'configuration' do
|
145
|
+
|
146
|
+
context 'with no configuration' do
|
147
|
+
|
148
|
+
let(:default_step_threshhold) { 10 }
|
149
|
+
|
150
|
+
context 'because configuration never happened' do
|
151
|
+
|
152
|
+
let(:unconfigured_test_model) do
|
153
|
+
model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
|
154
|
+
model.steps = []
|
155
|
+
(default_step_threshhold + 1).times { model.steps << :a_step }
|
156
|
+
|
157
|
+
model
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'defaults to a step threshold of 10 steps' do
|
161
|
+
results = subject.lint(unconfigured_test_model)
|
162
|
+
|
163
|
+
expect(results.first[:problem]).to match(/^Test has too many steps. #{unconfigured_test_model.steps.count} steps found \(max 10\)/)
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'because configuration did not set a step threshold' do
|
169
|
+
let(:configuration) { {} }
|
170
|
+
let(:configured_test_model) do
|
171
|
+
model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
|
172
|
+
model.steps = []
|
173
|
+
(default_step_threshhold + 1).times { model.steps << :a_step }
|
174
|
+
|
175
|
+
subject.configure(configuration)
|
176
|
+
|
177
|
+
model
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'defaults to a step threshold of 10 steps' do
|
181
|
+
results = subject.lint(configured_test_model)
|
182
|
+
|
183
|
+
expect(results.first[:problem]).to match(/^Test has too many steps. #{configured_test_model.steps.count} steps found \(max 10\)/)
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
context 'with configuration' do
|
192
|
+
|
193
|
+
let(:step_threshhold) { 3 }
|
194
|
+
let(:configuration) { { 'StepThreshold' => step_threshhold } }
|
195
|
+
let(:configured_test_model) do
|
196
|
+
model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
|
197
|
+
model.steps = []
|
198
|
+
(step_threshhold + 1).times { model.steps << :a_step }
|
199
|
+
|
200
|
+
subject.configure(configuration)
|
201
|
+
|
202
|
+
model
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'the step threshold used is the configured value' do
|
206
|
+
results = subject.lint(configured_test_model)
|
207
|
+
|
208
|
+
expect(results.first[:problem]).to match(/^Test has too many steps. #{configured_test_model.steps.count} steps found \(max #{step_threshhold}\)/)
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
142
215
|
end
|
143
216
|
|
144
217
|
context 'a non-test model' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuke_linter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Kessler
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-04-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cuke_modeler
|
@@ -137,19 +137,19 @@ dependencies:
|
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: 1.0.0
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: rainbow
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - "<"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
145
|
+
version: 4.0.0
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "<"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
152
|
+
version: 4.0.0
|
153
153
|
description:
|
154
154
|
email:
|
155
155
|
- morrow748@gmail.com
|
@@ -182,6 +182,8 @@ files:
|
|
182
182
|
- lib/cuke_linter/linters/test_with_too_many_steps_linter.rb
|
183
183
|
- lib/cuke_linter/version.rb
|
184
184
|
- testing/cucumber/features/command_line.feature
|
185
|
+
- testing/cucumber/features/configuration/configuring_linters.feature
|
186
|
+
- testing/cucumber/features/configuration/using_configurations.feature
|
185
187
|
- testing/cucumber/features/formatters/pretty_formatter.feature
|
186
188
|
- testing/cucumber/features/linters/default_linters.feature
|
187
189
|
- testing/cucumber/features/linters/example_without_name.feature
|
@@ -206,6 +208,7 @@ files:
|
|
206
208
|
- testing/rspec/spec/unit/cuke_linter_unit_spec.rb
|
207
209
|
- testing/rspec/spec/unit/formatters/formatter_unit_specs.rb
|
208
210
|
- testing/rspec/spec/unit/formatters/pretty_formatter_unit_spec.rb
|
211
|
+
- testing/rspec/spec/unit/linters/configurable_linter_unit_specs.rb
|
209
212
|
- testing/rspec/spec/unit/linters/example_without_name_linter_unit_spec.rb
|
210
213
|
- testing/rspec/spec/unit/linters/feature_without_scenarios_linter_unit_spec.rb
|
211
214
|
- testing/rspec/spec/unit/linters/linter_unit_specs.rb
|