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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/gherkin_lint.rb +150 -5
  3. metadata +16 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0115886cf68f342c7e96db6fed9b810821d39586
4
- data.tar.gz: bc8c412c92394916145f3b4998e1455a942f1ef0
3
+ metadata.gz: d3daa67e7b175ac10bdcc6698e7d49f45a294c4e
4
+ data.tar.gz: 5c7c0835a63af9a94fe99056f0a89f3d798dadbe
5
5
  SHA512:
6
- metadata.gz: 5b1fb9da007d9908a43ea4ae5d7b9c4cad6604b9030306e9a254cab5cc0680011b2de551bf16a2556951620cfc82279b2521f11e8ee53e8b4cc5088c6b5fa0df
7
- data.tar.gz: 1f5c003ef09b1bb24bf732816a43982ca7605ce541a60af1971094f694e3b30d03551e3de2fe87ef4fe1b2b97ef6234ec112d277c1bda2e2369d130aa0db3219
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
- description = 'Missing Action'
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
- scenarios do |file, feature, scenario|
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(/<.+>/).map { |val| val[1..-2] }
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.2
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-04 00:00:00.000000000 Z
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