cuke_linter 0.6.0 → 0.7.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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -1
  3. data/cuke_linter.gemspec +1 -0
  4. data/lib/cuke_linter.rb +24 -3
  5. data/lib/cuke_linter/linters/element_with_too_many_tags_linter.rb +41 -0
  6. data/lib/cuke_linter/linters/feature_without_name_linter.rb +20 -0
  7. data/lib/cuke_linter/linters/test_with_no_action_step_linter.rb +23 -0
  8. data/lib/cuke_linter/linters/test_with_no_name_linter.rb +20 -0
  9. data/lib/cuke_linter/linters/test_with_no_verification_step_linter.rb +23 -0
  10. data/lib/cuke_linter/linters/test_with_too_many_steps_linter.rb +1 -1
  11. data/lib/cuke_linter/version.rb +1 -1
  12. data/testing/cucumber/features/command_line.feature +6 -4
  13. data/testing/cucumber/features/configuration/configuring_linters.feature +36 -0
  14. data/testing/cucumber/features/linters/{background_does_more_than_setup_linter.feature → background_does_more_than_setup.feature} +2 -2
  15. data/testing/cucumber/features/linters/custom_linters.feature +3 -3
  16. data/testing/cucumber/features/linters/default_linters.feature +5 -1
  17. data/testing/cucumber/features/linters/element_with_too_many_tags.feature +70 -0
  18. data/testing/cucumber/features/linters/example_without_name.feature +6 -1
  19. data/testing/cucumber/features/linters/feature_without_description.feature +1 -1
  20. data/testing/cucumber/features/linters/feature_without_name.feature +18 -0
  21. data/testing/cucumber/features/linters/feature_without_scenarios.feature +1 -1
  22. data/testing/cucumber/features/linters/outline_with_single_example_row.feature +1 -1
  23. data/testing/cucumber/features/linters/{single_test_background_linter.feature → single_test_background.feature} +1 -1
  24. data/testing/cucumber/features/linters/step_too_long.feature +3 -3
  25. data/testing/cucumber/features/linters/step_with_end_period.feature +1 -1
  26. data/testing/cucumber/features/linters/test_with_no_action_step.feature +30 -0
  27. data/testing/cucumber/features/linters/test_with_no_name.feature +23 -0
  28. data/testing/cucumber/features/linters/test_with_no_verification_step.feature +31 -0
  29. data/testing/cucumber/features/linters/test_with_too_many_steps.feature +6 -6
  30. data/testing/cucumber/step_definitions/setup_steps.rb +24 -0
  31. data/testing/cucumber/step_definitions/verification_steps.rb +5 -1
  32. data/testing/model_factory.rb +1 -0
  33. data/testing/rspec/spec/integration/cli_integration_spec.rb +16 -11
  34. data/testing/rspec/spec/integration/cuke_linter_integration_spec.rb +37 -0
  35. data/testing/rspec/spec/integration/linters/element_with_too_many_tags_linter_integration_spec.rb +8 -0
  36. data/testing/rspec/spec/integration/linters/feature_without_name_linter_integration_spec.rb +8 -0
  37. data/testing/rspec/spec/integration/linters/test_with_no_action_step_integration_spec.rb +8 -0
  38. data/testing/rspec/spec/integration/linters/test_with_no_name_integration_spec.rb +8 -0
  39. data/testing/rspec/spec/integration/linters/test_with_no_verification_step_integration_spec.rb +8 -0
  40. data/testing/rspec/spec/unit/linters/element_with_too_many_tags_linter_unit_spec.rb +333 -0
  41. data/testing/rspec/spec/unit/linters/feature_without_name_linter_unit_spec.rb +112 -0
  42. data/testing/rspec/spec/unit/linters/step_with_too_many_characters_linter_unit_spec.rb +53 -52
  43. data/testing/rspec/spec/unit/linters/test_with_no_action_step_linter_unit_spec.rb +217 -0
  44. data/testing/rspec/spec/unit/linters/test_with_no_name_linter_unit_spec.rb +115 -0
  45. data/testing/rspec/spec/unit/linters/test_with_no_verification_step_linter_unit_spec.rb +217 -0
  46. data/testing/rspec/spec/unit/linters/test_with_too_many_steps_linter_unit_spec.rb +2 -2
  47. metadata +24 -4
@@ -25,7 +25,7 @@ RSpec.describe CukeLinter::StepWithTooManyCharactersLinter do
25
25
  end
26
26
 
27
27
  describe 'linting' do
28
-
28
+
29
29
  let(:default_character_threshold) { 80 }
30
30
 
31
31
  context 'when the step is too long' do
@@ -34,16 +34,16 @@ RSpec.describe CukeLinter::StepWithTooManyCharactersLinter do
34
34
  step = 'x' * (default_character_threshold + 1)
35
35
  CukeLinter::ModelFactory.generate_step_model(source_text: "* #{step}")
36
36
  end
37
-
37
+
38
38
  it 'reports a problem' do
39
39
  result = subject.lint(step_too_long_model)
40
40
 
41
41
  expect(result[:problem]).to match(/^Step is too long. \d+ characters found \(max 80\)/)
42
42
  end
43
-
43
+
44
44
  it 'records the location of the problem' do
45
45
  result = subject.lint(step_too_long_model)
46
-
46
+
47
47
  expect(result[:location]).to eq('path_to_file:4')
48
48
  end
49
49
 
@@ -58,19 +58,19 @@ RSpec.describe CukeLinter::StepWithTooManyCharactersLinter do
58
58
  end
59
59
 
60
60
  end
61
-
61
+
62
62
  context 'when the step is the maximum length' do
63
-
63
+
64
64
  let(:step_mex_length_model) do
65
65
  step = 'x' * default_character_threshold
66
66
  CukeLinter::ModelFactory.generate_step_model(source_text: "* #{step}")
67
67
  end
68
-
68
+
69
69
  it 'does not record a problem' do
70
70
  result = subject.lint(step_mex_length_model)
71
71
  expect(result).to eq(nil)
72
72
  end
73
-
73
+
74
74
  end
75
75
 
76
76
  context 'when the step is below the maximum length' do
@@ -103,50 +103,62 @@ RSpec.describe CukeLinter::StepWithTooManyCharactersLinter do
103
103
 
104
104
  end
105
105
 
106
+ context 'a non-step model' do
107
+
108
+ let(:test_model) { CukeModeler::Model.new }
109
+
110
+ it 'returns no result' do
111
+ result = subject.lint(test_model)
112
+
113
+ expect(result).to eq(nil)
114
+ end
115
+
116
+ end
117
+
106
118
  end
107
119
 
108
120
  describe 'configuration' do
109
121
 
110
122
  context 'with no configuration' do
111
123
 
112
- let(:default_character_threshold) { 80 }
113
-
114
- context 'because configuration never happened' do
115
-
116
- let(:default_model) do
117
- step = 'x' * (default_character_threshold + 1)
118
- CukeLinter::ModelFactory.generate_step_model(source_text: "* #{step}")
119
- end
120
-
121
- it 'defaults to a maximum of 80 characters' do
122
- result = subject.lint(default_model)
123
-
124
- expect( result[:problem]).to match(/^Step is too long. \d+ characters found \(max 80\)/)
125
- end
126
-
127
- end
128
-
129
- context 'because configuration did not set a step threshold' do
130
- let(:configuration) { {} }
131
- let(:configured_model) do
132
- subject.configure(configuration)
133
- step = 'x' * (default_character_threshold + 1)
134
- CukeLinter::ModelFactory.generate_step_model(source_text: "* #{step}")
135
- end
124
+ let(:default_character_threshold) { 80 }
125
+
126
+ context 'because configuration never happened' do
127
+
128
+ let(:default_model) do
129
+ step = 'x' * (default_character_threshold + 1)
130
+ CukeLinter::ModelFactory.generate_step_model(source_text: "* #{step}")
131
+ end
132
+
133
+ it 'defaults to a maximum of 80 characters' do
134
+ result = subject.lint(default_model)
135
+
136
+ expect(result[:problem]).to match(/^Step is too long. \d+ characters found \(max 80\)/)
137
+ end
136
138
 
137
- it 'defaults to a maximum of 80 characters' do
138
- result = subject.lint(configured_model)
139
-
140
- expect( result[:problem]).to match(/^Step is too long. \d+ characters found \(max 80\)/)
141
139
  end
142
140
 
143
- end
141
+ context 'because configuration did not set a step threshold' do
142
+ let(:configuration) { {} }
143
+ let(:configured_model) do
144
+ subject.configure(configuration)
145
+ step = 'x' * (default_character_threshold + 1)
146
+ CukeLinter::ModelFactory.generate_step_model(source_text: "* #{step}")
147
+ end
148
+
149
+ it 'defaults to a maximum of 80 characters' do
150
+ result = subject.lint(configured_model)
151
+
152
+ expect(result[:problem]).to match(/^Step is too long. \d+ characters found \(max 80\)/)
153
+ end
154
+
155
+ end
144
156
 
145
157
  end
146
158
 
147
159
  context 'when configured' do
148
160
  let(:character_threshold) { 10 }
149
- let(:configuration) { {'StepLengthThreshold' => character_threshold} }
161
+ let(:configuration) { { 'StepLengthThreshold' => character_threshold } }
150
162
 
151
163
  subject { linter = CukeLinter::StepWithTooManyCharactersLinter.new
152
164
  linter.configure(configuration)
@@ -156,25 +168,14 @@ RSpec.describe CukeLinter::StepWithTooManyCharactersLinter do
156
168
  step = 'x' * (character_threshold + 1)
157
169
  CukeLinter::ModelFactory.generate_step_model(source_text: "* #{step}")
158
170
  end
159
-
160
- it 'uses the maximum character length provided by configuration' do
161
- result = subject.lint(test_model)
162
-
163
- expect( result[:problem]).to match(/^Step is too long. \d+ characters found \(max 10\)/)
164
- end
165
-
166
- end
167
-
168
- context 'a non-step model' do
169
171
 
170
- let(:test_model) { CukeModeler::Model.new }
171
-
172
- it 'returns no result' do
172
+ it 'uses the maximum character length provided by configuration' do
173
173
  result = subject.lint(test_model)
174
174
 
175
- expect(result).to eq(nil)
175
+ expect(result[:problem]).to match(/^Step is too long. \d+ characters found \(max 10\)/)
176
176
  end
177
177
 
178
178
  end
179
+
179
180
  end
180
181
  end
@@ -0,0 +1,217 @@
1
+ require_relative '../../../../../environments/rspec_env'
2
+
3
+
4
+ RSpec.describe CukeLinter::TestWithNoActionStepLinter do
5
+
6
+ let(:good_data) do
7
+ CukeLinter::ModelFactory.generate_scenario_model(source_text: 'Scenario:
8
+ When an action step')
9
+ end
10
+
11
+ let(:bad_data) do
12
+ CukeLinter::ModelFactory.generate_scenario_model(source_text: 'Scenario:
13
+ * no action step')
14
+ end
15
+
16
+
17
+ it_should_behave_like 'a linter at the unit level'
18
+
19
+
20
+ it 'has a name' do
21
+ expect(subject.name).to eq('TestWithNoActionStepLinter')
22
+ end
23
+
24
+ describe 'linting' do
25
+
26
+ ['scenario', 'outline'].each do |model_type|
27
+
28
+ context "with a #{model_type} that has no action step" do
29
+
30
+ context 'because it has no steps' do
31
+
32
+ context 'because its steps are empty' do
33
+
34
+ let(:test_model) do
35
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model", parent_file_path: 'path_to_file')
36
+ model.steps = []
37
+
38
+ model
39
+ end
40
+
41
+ it 'records a problem' do
42
+ result = subject.lint(test_model)
43
+
44
+ expect(result[:problem]).to eq("Test does not have a 'When' step.")
45
+ end
46
+
47
+ it 'records the location of the problem' do
48
+ test_model.source_line = 1
49
+ result = subject.lint(test_model)
50
+ expect(result[:location]).to eq('path_to_file:1')
51
+
52
+ test_model.source_line = 3
53
+ result = subject.lint(test_model)
54
+ expect(result[:location]).to eq('path_to_file:3')
55
+ end
56
+
57
+ end
58
+
59
+ context 'because its steps are nil' do
60
+
61
+ let(:test_model) do
62
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model", parent_file_path: 'path_to_file')
63
+ model.steps = nil
64
+
65
+ model
66
+ end
67
+
68
+ it 'records a problem' do
69
+ result = subject.lint(test_model)
70
+
71
+ expect(result[:problem]).to eq("Test does not have a 'When' step.")
72
+ end
73
+
74
+ it 'records the location of the problem' do
75
+ test_model.source_line = 1
76
+ result = subject.lint(test_model)
77
+ expect(result[:location]).to eq('path_to_file:1')
78
+
79
+ test_model.source_line = 3
80
+ result = subject.lint(test_model)
81
+ expect(result[:location]).to eq('path_to_file:3')
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+ context 'because none of its steps is an action step' do
89
+
90
+ let(:test_model) do
91
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model", parent_file_path: 'path_to_file')
92
+ model.steps = [CukeModeler::Step.new('* not an action step')]
93
+
94
+ model
95
+ end
96
+
97
+ it 'records a problem' do
98
+ result = subject.lint(test_model)
99
+
100
+ expect(result[:problem]).to eq("Test does not have a 'When' step.")
101
+ end
102
+
103
+ it 'records the location of the problem' do
104
+ test_model.source_line = 1
105
+ result = subject.lint(test_model)
106
+ expect(result[:location]).to eq('path_to_file:1')
107
+
108
+ test_model.source_line = 3
109
+ result = subject.lint(test_model)
110
+ expect(result[:location]).to eq('path_to_file:3')
111
+ end
112
+
113
+ end
114
+
115
+ end
116
+
117
+ context "with a #{model_type} that does have an action step" do
118
+
119
+ context 'that comes from its background' do
120
+
121
+ let(:test_model) do
122
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
123
+ model.steps = []
124
+ background_model = CukeModeler::Background.new
125
+ background_model.steps = [CukeModeler::Step.new('When an action step')]
126
+ model.parent_model.background = background_model
127
+
128
+ model
129
+ end
130
+
131
+ it 'does not record a problem' do
132
+ expect(subject.lint(test_model)).to eq(nil)
133
+ end
134
+
135
+ end
136
+
137
+ context 'that is part of itself' do
138
+
139
+ let(:test_model) do
140
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
141
+ model.steps = [CukeModeler::Step.new('When an action step')]
142
+
143
+ model
144
+ end
145
+
146
+ it 'does not record a problem' do
147
+ expect(subject.lint(test_model)).to eq(nil)
148
+ end
149
+
150
+ end
151
+
152
+ end
153
+
154
+ end
155
+
156
+ ['scenario', 'outline'].each do |model_type|
157
+
158
+ context "with a #{model_type} that has a related background" do
159
+
160
+ let(:test_model) do
161
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
162
+ model.parent_model.background = background_model
163
+
164
+ model
165
+ end
166
+
167
+ context 'that has no background steps' do
168
+ context 'because its steps are empty' do
169
+
170
+ let(:background_model) do
171
+ model = CukeModeler::Background.new
172
+ model.steps = []
173
+
174
+ model
175
+ end
176
+
177
+ it 'can handle it' do
178
+ expect { subject.lint(test_model) }.to_not raise_error
179
+ end
180
+
181
+ end
182
+
183
+ context 'because its steps are nil' do
184
+
185
+ let(:background_model) do
186
+ model = CukeModeler::Background.new
187
+ model.steps = nil
188
+
189
+ model
190
+ end
191
+
192
+ it 'can handle it' do
193
+ expect { subject.lint(test_model) }.to_not raise_error
194
+ end
195
+
196
+ end
197
+
198
+ end
199
+
200
+ end
201
+
202
+ end
203
+
204
+
205
+ context 'a non-test model' do
206
+
207
+ let(:test_model) { CukeModeler::Model.new }
208
+
209
+ it 'returns no result' do
210
+ result = subject.lint(test_model)
211
+
212
+ expect(result).to eq(nil)
213
+ end
214
+
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,115 @@
1
+ require_relative '../../../../../environments/rspec_env'
2
+
3
+
4
+ RSpec.describe CukeLinter::TestWithNoNameLinter do
5
+
6
+ let(:good_data) do
7
+ CukeLinter::ModelFactory.generate_scenario_model(source_text: 'Scenario: some name')
8
+ end
9
+
10
+ let(:bad_data) do
11
+ CukeLinter::ModelFactory.generate_scenario_model(source_text: 'Scenario:')
12
+ end
13
+
14
+
15
+ it_should_behave_like 'a linter at the unit level'
16
+
17
+
18
+ it 'has a name' do
19
+ expect(subject.name).to eq('TestWithNoNameLinter')
20
+ end
21
+
22
+ describe 'linting' do
23
+
24
+ ['scenario', 'outline'].each do |model_type|
25
+
26
+ context "with a #{model_type} that has no name" do
27
+
28
+ context 'because its name is empty' do
29
+
30
+ let(:test_model) do
31
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model", parent_file_path: 'path_to_file')
32
+ model.name = ''
33
+
34
+ model
35
+ end
36
+
37
+ it 'records a problem' do
38
+ result = subject.lint(test_model)
39
+
40
+ expect(result[:problem]).to eq('Test does not have a name.')
41
+ end
42
+
43
+ it 'records the location of the problem' do
44
+ test_model.source_line = 1
45
+ result = subject.lint(test_model)
46
+ expect(result[:location]).to eq('path_to_file:1')
47
+
48
+ test_model.source_line = 3
49
+ result = subject.lint(test_model)
50
+ expect(result[:location]).to eq('path_to_file:3')
51
+ end
52
+
53
+ end
54
+
55
+ context 'because its name is nil' do
56
+
57
+ let(:test_model) do
58
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model", parent_file_path: 'path_to_file')
59
+ model.name = nil
60
+
61
+ model
62
+ end
63
+
64
+ it 'records a problem' do
65
+ result = subject.lint(test_model)
66
+
67
+ expect(result[:problem]).to eq('Test does not have a name.')
68
+ end
69
+
70
+ it 'records the location of the problem' do
71
+ test_model.source_line = 1
72
+ result = subject.lint(test_model)
73
+ expect(result[:location]).to eq('path_to_file:1')
74
+
75
+ test_model.source_line = 3
76
+ result = subject.lint(test_model)
77
+ expect(result[:location]).to eq('path_to_file:3')
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ context "with a #{model_type} that does have a name" do
85
+
86
+ let(:test_model) do
87
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
88
+ model.name = 'foo'
89
+
90
+ model
91
+ end
92
+
93
+ it 'does not record a problem' do
94
+ expect(subject.lint(test_model)).to eq(nil)
95
+ end
96
+
97
+ end
98
+
99
+ end
100
+
101
+ context 'a non-test model' do
102
+
103
+ let(:test_model) { CukeModeler::Model.new }
104
+
105
+ it 'returns no result' do
106
+ result = subject.lint(test_model)
107
+
108
+ expect(result).to eq(nil)
109
+ end
110
+
111
+ end
112
+
113
+ end
114
+
115
+ end