cuke_linter 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|