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
@@ -0,0 +1,8 @@
1
+ require_relative '../../../../../environments/rspec_env'
2
+
3
+
4
+ RSpec.describe CukeLinter::TestWithNoNameLinter do
5
+
6
+ it_should_behave_like 'a linter at the integration level'
7
+
8
+ end
@@ -0,0 +1,8 @@
1
+ require_relative '../../../../../environments/rspec_env'
2
+
3
+
4
+ RSpec.describe CukeLinter::TestWithNoVerificationStepLinter do
5
+
6
+ it_should_behave_like 'a linter at the integration level'
7
+
8
+ end
@@ -0,0 +1,333 @@
1
+ require_relative '../../../../../environments/rspec_env'
2
+
3
+
4
+ RSpec.describe CukeLinter::ElementWithTooManyTagsLinter do
5
+
6
+ let(:good_data) do
7
+ model = CukeLinter::ModelFactory.generate_scenario_model
8
+ model.tags = [:tag_1]
9
+
10
+ model
11
+ end
12
+
13
+ let(:bad_data) do
14
+ model = CukeLinter::ModelFactory.generate_scenario_model
15
+ model.tags = [:tag_1,
16
+ :tag_2,
17
+ :tag_3,
18
+ :tag_4,
19
+ :tag_5,
20
+ :tag_6]
21
+
22
+ model
23
+ end
24
+
25
+
26
+ it_should_behave_like 'a linter at the unit level'
27
+ it_should_behave_like 'a configurable linter at the unit level'
28
+
29
+
30
+ it 'has a name' do
31
+ expect(subject.name).to eq('ElementWithTooManyTagsLinter')
32
+ end
33
+
34
+ describe 'linting' do
35
+
36
+ ['feature', 'scenario', 'outline', 'example'].each do |model_type|
37
+
38
+ context "with a #{model_type} that has too many tags" do
39
+
40
+ let(:test_model) do
41
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model", parent_file_path: 'path_to_file')
42
+ model.tags = [:tag_1,
43
+ :tag_2,
44
+ :tag_3,
45
+ :tag_4,
46
+ :tag_5,
47
+ :tag_6]
48
+
49
+ model
50
+ end
51
+
52
+ it 'records a problem' do
53
+ result = subject.lint(test_model)
54
+
55
+ expect(result[:problem]).to match(/^#{model_type.capitalize} has too many tags. \d+ tags found \(max 5\)\.$/)
56
+ end
57
+
58
+ it 'records the location of the problem' do
59
+ test_model.source_line = 1
60
+ result = subject.lint(test_model)
61
+ expect(result[:location]).to eq('path_to_file:1')
62
+
63
+ test_model.source_line = 3
64
+ result = subject.lint(test_model)
65
+ expect(result[:location]).to eq('path_to_file:3')
66
+ end
67
+
68
+ it 'includes the number of tags found in the problem record' do
69
+ tag_count = test_model.tags.count
70
+ result = subject.lint(test_model)
71
+ expect(result[:problem]).to eq("#{model_type.capitalize} has too many tags. #{tag_count} tags found (max 5).")
72
+
73
+ test_model.tags << :another_tag
74
+ result = subject.lint(test_model)
75
+ expect(result[:problem]).to eq("#{model_type.capitalize} has too many tags. #{tag_count + 1} tags found (max 5).")
76
+ end
77
+
78
+ end
79
+
80
+ context "with a #{model_type} that does not have too many tags" do
81
+
82
+ context 'because it has 5 tags' do
83
+
84
+ let(:test_model) do
85
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model", parent_file_path: 'path_to_file')
86
+ model.tags = [:tag_1,
87
+ :tag_2,
88
+ :tag_3,
89
+ :tag_4,
90
+ :tag_5]
91
+
92
+ model
93
+ end
94
+
95
+ it 'does not record a problem' do
96
+ expect(subject.lint(test_model)).to eq(nil)
97
+ end
98
+
99
+ end
100
+
101
+ context 'because it has fewer than 5 tags' do
102
+
103
+ let(:test_model) do
104
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model", parent_file_path: 'path_to_file')
105
+ model.tags = [:tag_1]
106
+
107
+ model
108
+ end
109
+
110
+ it 'does not record a problem' do
111
+ expect(subject.lint(test_model)).to eq(nil)
112
+ end
113
+
114
+ end
115
+
116
+ context 'because it has no tags' do
117
+
118
+ context 'because its tags are empty' do
119
+
120
+ let(:test_model) do
121
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model", parent_file_path: 'path_to_file')
122
+ model.tags = []
123
+
124
+ model
125
+ end
126
+
127
+ it 'does not record a problem' do
128
+ expect(subject.lint(test_model)).to eq(nil)
129
+ end
130
+
131
+ end
132
+
133
+ context 'because its tags are nil' do
134
+
135
+ let(:test_model) do
136
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model", parent_file_path: 'path_to_file')
137
+ model.tags = nil
138
+
139
+ model
140
+ end
141
+
142
+ it 'does not record a problem' do
143
+ expect(subject.lint(test_model)).to eq(nil)
144
+ end
145
+
146
+ end
147
+
148
+ end
149
+
150
+ end
151
+
152
+
153
+ describe 'configuration' do
154
+
155
+ let(:default_tag_threshold) { 5 }
156
+
157
+
158
+ describe 'tag threshold configuration' do
159
+
160
+ context 'with no configuration' do
161
+
162
+ context 'because configuration never happened' do
163
+
164
+ let(:unconfigured_test_model) do
165
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
166
+ model.tags = []
167
+ (default_tag_threshold + 1).times { model.tags << :a_tag }
168
+
169
+ model
170
+ end
171
+
172
+ it 'defaults to a tag threshold of 5 tags' do
173
+ result = subject.lint(unconfigured_test_model)
174
+
175
+ expect(result[:problem]).to eq("#{model_type.capitalize} has too many tags. #{unconfigured_test_model.tags.count} tags found (max 5).")
176
+ end
177
+
178
+ end
179
+
180
+ context 'because configuration did not set a tag threshold' do
181
+
182
+ let(:configuration) { {} }
183
+ let(:test_model) do
184
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
185
+ model.tags = []
186
+ (default_tag_threshold + 1).times { model.tags << :a_tag }
187
+
188
+ model
189
+ end
190
+
191
+ before(:each) do
192
+ subject.configure(configuration)
193
+ end
194
+
195
+ it 'defaults to a tag threshold of 5 tags' do
196
+ result = subject.lint(test_model)
197
+
198
+ expect(result[:problem]).to eq("#{model_type.capitalize} has too many tags. #{test_model.tags.count} tags found (max 5).")
199
+ end
200
+
201
+ end
202
+
203
+ end
204
+
205
+ context 'with configuration' do
206
+
207
+ let(:tag_threshold) { 3 }
208
+ let(:configuration) { { 'TagCountThreshold' => tag_threshold } }
209
+
210
+ before(:each) do
211
+ subject.configure(configuration)
212
+ end
213
+
214
+ let(:test_model) do
215
+ model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
216
+ model.tags = []
217
+ (tag_threshold + 1).times { model.tags << :a_tag }
218
+
219
+ model
220
+ end
221
+
222
+ it 'the tag threshold used is the configured value' do
223
+ result = subject.lint(test_model)
224
+
225
+ expect(result[:problem]).to eq("#{model_type.capitalize} has too many tags. #{test_model.tags.count} tags found (max #{tag_threshold}).")
226
+ end
227
+
228
+ end
229
+
230
+ end
231
+
232
+
233
+ describe 'tag inheritance configuration' do
234
+
235
+ let(:test_model_with_inherited_tags) do
236
+ test_model = CukeLinter::ModelFactory.send("generate_#{model_type}_model")
237
+ test_model.tags = []
238
+ (default_tag_threshold).times { test_model.tags << :a_tag }
239
+
240
+ ancestor_model = CukeLinter::ModelFactory.generate_lintable_model
241
+ ancestor_model.tags = [:an_extra_tag]
242
+
243
+ test_model.parent_model = ancestor_model
244
+
245
+ test_model
246
+ end
247
+
248
+
249
+ context 'with no configuration' do
250
+
251
+ context 'because configuration never happened' do
252
+
253
+ it 'does not include inherited tags' do
254
+ result = subject.lint(test_model_with_inherited_tags)
255
+
256
+ expect(result).to eq(nil)
257
+ end
258
+
259
+ end
260
+
261
+ context 'because configuration did not set tag inheritance' do
262
+
263
+ let(:configuration) { {} }
264
+
265
+ before(:each) do
266
+ subject.configure(configuration)
267
+ end
268
+
269
+ it 'does not include inherited tags' do
270
+ result = subject.lint(test_model_with_inherited_tags)
271
+
272
+ expect(result).to eq(nil)
273
+ end
274
+
275
+ end
276
+
277
+ end
278
+
279
+ context 'with configuration' do
280
+
281
+ before(:each) do
282
+ subject.configure(configuration)
283
+ end
284
+
285
+ context 'enabling tag inheritance' do
286
+
287
+ let(:configuration) { { 'CountInheritedTags' => true } }
288
+
289
+ it 'does include inherited tags' do
290
+ result = subject.lint(test_model_with_inherited_tags)
291
+
292
+ expect(result).to_not be_nil
293
+ expect(result[:problem]).to eq("#{model_type.capitalize} has too many tags. #{test_model_with_inherited_tags.all_tags.count} tags found (max #{default_tag_threshold}).")
294
+ end
295
+
296
+ end
297
+
298
+ context 'disabling tag inheritance' do
299
+
300
+ let(:configuration) { { 'CountInheritedTags' => false } }
301
+
302
+ it 'does not include inherited tags' do
303
+ result = subject.lint(test_model_with_inherited_tags)
304
+
305
+ expect(result).to eq(nil)
306
+ end
307
+
308
+ end
309
+
310
+ end
311
+
312
+ end
313
+
314
+ end
315
+
316
+ end
317
+
318
+
319
+ context 'a non-taggable model' do
320
+
321
+ let(:test_model) { CukeModeler::Model.new }
322
+
323
+ it 'returns no result' do
324
+ result = subject.lint(test_model)
325
+
326
+ expect(result).to eq(nil)
327
+ end
328
+
329
+ end
330
+
331
+ end
332
+
333
+ end
@@ -0,0 +1,112 @@
1
+ require_relative '../../../../../environments/rspec_env'
2
+
3
+
4
+ RSpec.describe CukeLinter::FeatureWithoutNameLinter do
5
+
6
+ let(:good_data) do
7
+ CukeLinter::ModelFactory.generate_feature_model(source_text: 'Feature: some name')
8
+ end
9
+
10
+ let(:bad_data) do
11
+ CukeLinter::ModelFactory.generate_feature_model(source_text: 'Feature:')
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('FeatureWithoutNameLinter')
20
+ end
21
+
22
+ describe 'linting' do
23
+
24
+ context 'with a feature that has no name' do
25
+
26
+ context 'because its name is empty' do
27
+
28
+ let(:test_model) do
29
+ model = CukeLinter::ModelFactory.generate_feature_model(parent_file_path: 'path_to_file')
30
+ model.name = ''
31
+
32
+ model
33
+ end
34
+
35
+ it 'records a problem' do
36
+ result = subject.lint(test_model)
37
+
38
+ expect(result[:problem]).to eq('Feature does not have a name.')
39
+ end
40
+
41
+ it 'records the location of the problem' do
42
+ test_model.source_line = 1
43
+ result = subject.lint(test_model)
44
+ expect(result[:location]).to eq('path_to_file:1')
45
+
46
+ test_model.source_line = 3
47
+ result = subject.lint(test_model)
48
+ expect(result[:location]).to eq('path_to_file:3')
49
+ end
50
+
51
+ end
52
+
53
+ context 'because its name is nil' do
54
+
55
+ let(:test_model) do
56
+ model = CukeLinter::ModelFactory.generate_feature_model(parent_file_path: 'path_to_file')
57
+ model.name = nil
58
+
59
+ model
60
+ end
61
+
62
+ it 'records a problem' do
63
+ result = subject.lint(test_model)
64
+
65
+ expect(result[:problem]).to eq('Feature does not have a name.')
66
+ end
67
+
68
+ it 'records the location of the problem' do
69
+ test_model.source_line = 1
70
+ result = subject.lint(test_model)
71
+ expect(result[:location]).to eq('path_to_file:1')
72
+
73
+ test_model.source_line = 3
74
+ result = subject.lint(test_model)
75
+ expect(result[:location]).to eq('path_to_file:3')
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ context 'with a feature that does have a name' do
83
+
84
+ let(:test_model) do
85
+ model = CukeLinter::ModelFactory.generate_feature_model
86
+ model.name = 'foo'
87
+
88
+ model
89
+ end
90
+
91
+ it 'does not record a problem' do
92
+ expect(subject.lint(test_model)).to eq(nil)
93
+ end
94
+
95
+ end
96
+
97
+
98
+ context 'a non-feature model' do
99
+
100
+ let(:test_model) { CukeModeler::Model.new }
101
+
102
+ it 'returns no result' do
103
+ result = subject.lint(test_model)
104
+
105
+ expect(result).to eq(nil)
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+
112
+ end