gherkin_lint 0.0.2 → 0.0.3
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/lib/gherkin_lint.rb +150 -5
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3daa67e7b175ac10bdcc6698e7d49f45a294c4e
|
4
|
+
data.tar.gz: 5c7c0835a63af9a94fe99056f0a89f3d798dadbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5538c69efcd96aeabc32aa6bbb4746edddc89e71f8823c00ecdc3e6862529b406dd738a8748a8a3ed530a233eb7aff669b92aaf83494008a9efebdbf3a98cfd5
|
7
|
+
data.tar.gz: a867fa1ea399b7f5f564a0be95c411df25582cc8a0d06278b29f18ddc03e4dbecdb98c3c429e64ad43fcad59511172053085410936ef38d85342b98b8f15729f
|
data/lib/gherkin_lint.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'amatch'
|
1
2
|
require 'gherkin/formatter/json_formatter'
|
2
3
|
require 'gherkin/parser/parser'
|
3
4
|
require 'stringio'
|
@@ -59,6 +60,31 @@ class GherkinLint
|
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
63
|
+
def filled_scenarios
|
64
|
+
@files.each do |file, content|
|
65
|
+
content.each do |feature|
|
66
|
+
next unless feature.key? 'elements'
|
67
|
+
feature['elements'].each do |scenario|
|
68
|
+
next if scenario['keyword'] == 'Background'
|
69
|
+
next unless scenario.include? 'steps'
|
70
|
+
yield(file, feature, scenario)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def steps
|
77
|
+
@files.each do |file, content|
|
78
|
+
content.each do |feature|
|
79
|
+
next unless feature.key? 'elements'
|
80
|
+
feature['elements'].each do |scenario|
|
81
|
+
next unless scenario.include? 'steps'
|
82
|
+
scenario['steps'].each { |step| yield(file, feature, scenario, step) }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
62
88
|
def backgrounds
|
63
89
|
@files.each do |file, content|
|
64
90
|
content.each do |feature|
|
@@ -133,6 +159,17 @@ class GherkinLint
|
|
133
159
|
end
|
134
160
|
end
|
135
161
|
|
162
|
+
# service class to lint for too long steps
|
163
|
+
class TooLongStep < Linter
|
164
|
+
def lint
|
165
|
+
steps do |file, feature, scenario, step|
|
166
|
+
next if step['name'].length < 80
|
167
|
+
references = [reference(file, feature, scenario, step)]
|
168
|
+
add_issue(references, "Used #{step['name'].length} characters")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
136
173
|
# service class to lint for missing verifications
|
137
174
|
class MissingVerification < Linter
|
138
175
|
def lint
|
@@ -254,8 +291,7 @@ class GherkinLint
|
|
254
291
|
steps.each do |step|
|
255
292
|
break if step['keyword'] == 'When '
|
256
293
|
references = [reference(file, feature, scenario, step)]
|
257
|
-
|
258
|
-
add_issue(references, description) if step['keyword'] == 'Then '
|
294
|
+
add_issue(references, 'Missing Action') if step['keyword'] == 'Then '
|
259
295
|
end
|
260
296
|
end
|
261
297
|
end
|
@@ -275,6 +311,31 @@ class GherkinLint
|
|
275
311
|
end
|
276
312
|
end
|
277
313
|
|
314
|
+
# service class to lint for too clumsy scenarios
|
315
|
+
class TooClumsy < Linter
|
316
|
+
def lint
|
317
|
+
scenarios do |file, feature, scenario|
|
318
|
+
next unless scenario.include? 'steps'
|
319
|
+
characters = scenario['steps'].map { |step| step['name'].length }.inject(0, :+)
|
320
|
+
next if characters < 400
|
321
|
+
references = [reference(file, feature, scenario)]
|
322
|
+
add_issue(references, "Used #{characters} Characters")
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
# service class to lint for too many steps
|
328
|
+
class TooManySteps < Linter
|
329
|
+
def lint
|
330
|
+
scenarios do |file, feature, scenario|
|
331
|
+
next unless scenario.include? 'steps'
|
332
|
+
next if scenario['steps'].length < 10
|
333
|
+
references = [reference(file, feature, scenario)]
|
334
|
+
add_issue(references, "Used #{scenario['steps'].length} Steps")
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
278
339
|
# service class to lint for invalid file names
|
279
340
|
class InvalidFileName < Linter
|
280
341
|
def lint
|
@@ -290,7 +351,7 @@ class GherkinLint
|
|
290
351
|
# service class to lint for unknown variables
|
291
352
|
class UnknownVariable < Linter
|
292
353
|
def lint
|
293
|
-
|
354
|
+
filled_scenarios do |file, feature, scenario|
|
294
355
|
known_vars = known_variables scenario
|
295
356
|
scenario['steps'].each do |step|
|
296
357
|
step_vars(step).each do |used_var|
|
@@ -314,7 +375,7 @@ class GherkinLint
|
|
314
375
|
end
|
315
376
|
|
316
377
|
def gather_vars(string)
|
317
|
-
string.scan(
|
378
|
+
string.scan(/<.+?>/).map { |val| val[1..-2] }
|
318
379
|
end
|
319
380
|
|
320
381
|
def known_variables(scenario)
|
@@ -379,6 +440,85 @@ class GherkinLint
|
|
379
440
|
end
|
380
441
|
end
|
381
442
|
|
443
|
+
# service class to lint for using background
|
444
|
+
class UseBackground < Linter
|
445
|
+
def lint
|
446
|
+
features do |file, feature|
|
447
|
+
givens = gather_givens feature
|
448
|
+
next if givens.length <= 1
|
449
|
+
next if givens.uniq.length > 1
|
450
|
+
references = [reference(file, feature)]
|
451
|
+
add_issue(references, "Step '#{givens.uniq.first}' should be part of background")
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
def gather_givens(feature)
|
456
|
+
result = []
|
457
|
+
return result unless feature.include? 'elements'
|
458
|
+
feature['elements'].each do |scenario|
|
459
|
+
next if scenario['keyword'] == 'Background'
|
460
|
+
next unless scenario.include? 'steps'
|
461
|
+
return [] unless scenario['steps'].first['keyword'] == 'Given '
|
462
|
+
result.push scenario['steps'].first['name']
|
463
|
+
end
|
464
|
+
result
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
# service class to lint for using outline
|
469
|
+
class UseOutline < Linter
|
470
|
+
def lint
|
471
|
+
features do |file, feature|
|
472
|
+
check_similarity gather_scenarios(file, feature)
|
473
|
+
end
|
474
|
+
end
|
475
|
+
|
476
|
+
def check_similarity(scenarios)
|
477
|
+
scenarios.product(scenarios) do |lhs, rhs|
|
478
|
+
next if lhs == rhs
|
479
|
+
next if lhs[:reference] > rhs[:reference]
|
480
|
+
similarity = determine_similarity(lhs[:text], rhs[:text])
|
481
|
+
next unless similarity >= 0.95
|
482
|
+
references = [lhs[:reference], rhs[:reference]]
|
483
|
+
add_issue(references, "Scenarios are similar by #{similarity.round(3) * 100} %")
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
def determine_similarity(lhs, rhs)
|
488
|
+
matcher = Amatch::Jaro.new lhs
|
489
|
+
matcher.match rhs
|
490
|
+
end
|
491
|
+
|
492
|
+
def gather_scenarios(file, feature)
|
493
|
+
scenarios = []
|
494
|
+
return scenarios unless feature.include? 'elements'
|
495
|
+
feature['elements'].each do |scenario|
|
496
|
+
next unless scenario['keyword'] == 'Scenario'
|
497
|
+
next unless scenario.include? 'steps'
|
498
|
+
scenarios.push generate_reference(file, feature, scenario)
|
499
|
+
end
|
500
|
+
scenarios
|
501
|
+
end
|
502
|
+
|
503
|
+
def generate_reference(file, feature, scenario)
|
504
|
+
reference = {}
|
505
|
+
reference[:reference] = reference(file, feature, scenario)
|
506
|
+
reference[:text] = scenario['steps'].map { |step| render(step) }.join ' '
|
507
|
+
reference
|
508
|
+
end
|
509
|
+
|
510
|
+
def render(step)
|
511
|
+
value = "#{step['keyword']}#{step['name']}"
|
512
|
+
value += "\n#{step['doc_string']['value']}" if step.include? 'doc_string'
|
513
|
+
if step.include? 'rows'
|
514
|
+
value += step['rows'].map do |row|
|
515
|
+
row['cells'].join '|'
|
516
|
+
end.join "|\n"
|
517
|
+
end
|
518
|
+
value
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
382
522
|
LINTER = [
|
383
523
|
AvoidPeriod,
|
384
524
|
BackgroundDoesMoreThanSetup,
|
@@ -392,9 +532,14 @@ class GherkinLint
|
|
392
532
|
MissingVerification,
|
393
533
|
InvalidFileName,
|
394
534
|
InvalidStepFlow,
|
535
|
+
TooClumsy,
|
536
|
+
TooManySteps,
|
537
|
+
TooLongStep,
|
395
538
|
UniqueScenarioNames,
|
396
539
|
UnknownVariable,
|
397
|
-
UnusedVariable
|
540
|
+
UnusedVariable,
|
541
|
+
UseBackground,
|
542
|
+
UseOutline
|
398
543
|
]
|
399
544
|
|
400
545
|
def initialize
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gherkin_lint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stefan Rohe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gherkin
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 1.3.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: amatch
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.3.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.3.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: aruba
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|