gherkin_language 0.0.7 → 0.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 04aee53e8b36b777bf0889ce6b0cdcd94fdef265
4
- data.tar.gz: 54aaa1ba0d8625f05aeb8ee79e09878657988957
3
+ metadata.gz: db5be66787bff52612008a4e2999084191cdff53
4
+ data.tar.gz: 294d5c8d58ea483b2bb877f90cdbe4e7a0bae614
5
5
  SHA512:
6
- metadata.gz: b3186581735b4460df28c170f865f4ee3cbb4e203cba63d77e78c3d6e1d9622a777483b9e104749972847c1a7eca36f93cd89c7f46afad1fca6be17d42903f12
7
- data.tar.gz: 4563bb4bdfe7815bf4573c8352160c6db8fb86d01a120c0ae1155a053f7fdd423cc5e012f0a607f9d7ac17b98019c36a123147ae51d6571c555b863ad2cc0dc1
6
+ metadata.gz: 65eb341ef2cf91a80d11c42f531c20a1dc994e751dd0b538f579efb14a8065ef5acdb41ff7aedf7fc903a6c528b7261a00b30b6c7e9064861c004fd52aac2790
7
+ data.tar.gz: e3916bf3b624a8b8564122e9d4d05f16cbd1cee536d77e0754e88669377519fcdfbb27b507698bb63ae3e37cc3fc334cdc28360623a4274ee90862c466a70cc2
data/.rubocop.yml CHANGED
@@ -7,21 +7,21 @@
7
7
 
8
8
  # Offense count: 5
9
9
  Metrics/AbcSize:
10
- Max: 48
10
+ Max: 36
11
11
 
12
12
  # Offense count: 2
13
13
  # Configuration parameters: CountComments.
14
14
  Metrics/ClassLength:
15
- Max: 171
15
+ Max: 172
16
16
 
17
17
  # Offense count: 2
18
18
  Metrics/CyclomaticComplexity:
19
- Max: 11
19
+ Max: 7
20
20
 
21
21
  # Offense count: 17
22
22
  # Configuration parameters: AllowURI, URISchemes.
23
23
  Metrics/LineLength:
24
- Max: 121
24
+ Max: 117
25
25
 
26
26
  # Offense count: 8
27
27
  # Configuration parameters: CountComments.
@@ -34,5 +34,5 @@ Metrics/ParameterLists:
34
34
  Max: 8
35
35
 
36
36
  # Offense count: 2
37
- Metrics/PerceivedComplexity:
38
- Max: 12
37
+ #Metrics/PerceivedComplexity:
38
+ # Max: 8
data/README.md CHANGED
@@ -23,6 +23,8 @@ To tag all words used, start it with `--tag`. This allows to build up a glossary
23
23
 
24
24
  To ignore specific rules, mention them with an `--ignore RULE`. This allows to bypass the checks.
25
25
 
26
+ To check for confused words, based on ngrams, add `--ngram`. Please note, that it requires much disk space and time.
27
+
26
28
 
27
29
  Glossary
28
30
  --------
data/Rakefile CHANGED
@@ -18,7 +18,7 @@ task test: :cucumber
18
18
 
19
19
  desc 'Publishes the Gem'
20
20
  task push: :build do
21
- sh 'gem push gherkin_language-0.0.7.gem'
21
+ sh 'gem push gherkin_language-0.0.8.gem'
22
22
  end
23
23
 
24
24
  desc 'Checks ruby style'
data/bin/gherkin_language CHANGED
@@ -17,9 +17,12 @@ OptionParser.new do |opts|
17
17
  opts.on('--no-cache', 'do not use cache') do |no_cache|
18
18
  options[:no_cache] = no_cache
19
19
  end
20
+ opts.on('--ngram', 'check based on ngrams') do |ngram|
21
+ options[:ngram] = ngram
22
+ end
20
23
  end.parse!
21
24
 
22
- language = GherkinLanguage.new(options.key? :no_cache)
25
+ language = GherkinLanguage.new(options.key?(:no_cache), options.key?(:ngram))
23
26
 
24
27
  if options.key? :sentences
25
28
  ARGV.each { |file| puts language.extract_sentences language.parse file }
@@ -0,0 +1,52 @@
1
+ Feature: Confused Words
2
+ As a Business Analyst
3
+ I want to be informed for confused words
4
+ so that I know when I'm using wrong words
5
+
6
+ Background:
7
+ Given a file named "confused_words.rb" with:
8
+ """
9
+ $LOAD_PATH << '../../lib'
10
+ require 'gherkin_language'
11
+
12
+ no_cache = true
13
+ ngrams = true
14
+ language = GherkinLanguage.new(no_cache, ngrams)
15
+ language.analyze 'test.feature'
16
+ exit language.report
17
+
18
+ """
19
+
20
+ Scenario: Warns for confused word
21
+ Given a file named "test.feature" with:
22
+ """
23
+ Feature: Test
24
+ Scenario: Tag
25
+ Given I do not now where it is
26
+ When execute
27
+ Then pass
28
+ """
29
+ When I run `ruby confused_words.rb`
30
+ Then it should fail with exactly:
31
+ """
32
+ [non-conformance] CONFUSION_RULE
33
+ Statistic suggests that 'know' (to be aware of) might be the correct word here, not 'now' (in this moment). Please check.
34
+ Context: Given I do not now where it is when execute then pass
35
+ Replacements: know
36
+ References: test.feature
37
+ """
38
+
39
+ Scenario: Accept non confused words
40
+ Given a file named "test.feature" with:
41
+ """
42
+ Feature: Test
43
+ Scenario: Tag
44
+ Given I do not know where it is
45
+ When execute
46
+ Then pass
47
+ """
48
+ When I run `ruby confused_words.rb`
49
+ Then it should pass with exactly:
50
+ """
51
+
52
+ """
@@ -80,18 +80,18 @@ Feature: Sentences
80
80
  """
81
81
  Feature: Test
82
82
  Scenario Outline: Test
83
- When <A> <B>
84
- Then <C>
83
+ When <A>
84
+ Then <B>
85
85
 
86
86
  Examples: Table
87
- | A |
88
- | 1 |
89
- | 2 |
87
+ | A | B |
88
+ | 1 | 3 |
89
+ | 2 | 4 |
90
90
 
91
91
  Examples: Second Table
92
- | B | C |
93
- | 3 | 5 |
94
- | 4 | 6 |
92
+ | B | A |
93
+ | 5 | 7 |
94
+ | 6 | 8 |
95
95
  """
96
96
  When I run `ruby extract_sentences.rb`
97
97
  Then it should pass with:
@@ -99,11 +99,11 @@ Feature: Sentences
99
99
  Test
100
100
  Test
101
101
  Table
102
+ When 1 then 3
103
+ When 2 then 4
102
104
  Second Table
103
- When 1 3 then 5
104
- When 1 4 then 6
105
- When 2 3 then 5
106
- When 2 4 then 6
105
+ When 7 then 5
106
+ When 8 then 6
107
107
  """
108
108
 
109
109
  Scenario: Extract Sentences considers feature description
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'gherkin_language'
3
- s.version = '0.0.7'
3
+ s.version = '0.0.8'
4
4
  s.date = '2015-10-04'
5
5
  s.summary = 'Gherkin Language'
6
6
  s.description = 'Check language of Gherkin Files'
@@ -1,6 +1,8 @@
1
1
  # encoding: utf-8
2
2
  require 'gherkin/formatter/json_formatter'
3
3
  require 'gherkin/parser/parser'
4
+ require 'gherkin_language/error'
5
+ require 'gherkin_language/language_tool_process'
4
6
  require 'rexml/document'
5
7
  require 'stringio'
6
8
  require 'multi_json'
@@ -14,143 +16,7 @@ require 'digest'
14
16
 
15
17
  # gherkin utilities
16
18
  class GherkinLanguage
17
- # This service class provides access to language tool process.
18
- class LanguageToolProcess
19
- attr_accessor :errors, :unknown_words
20
-
21
- VERSION = 'LanguageTool-3.0'
22
- URL = "https://www.languagetool.org/download/#{VERSION}.zip"
23
-
24
- # This value entity class represents a language error
25
- class Error
26
- attr_accessor :category, :context, :issuetype, :message, :replacements, :rule, :from_y, :to_y
27
-
28
- def initialize(category, context, issuetype, message, replacements, rule, from_y, to_y)
29
- @category = category
30
- @context = context
31
- @issuetype = issuetype
32
- @message = message
33
- @replacements = replacements
34
- @rule = rule
35
- @from_y = from_y
36
- @to_y = to_y
37
- end
38
-
39
- def str(references)
40
- (red("[#{@issuetype}] #{@rule}\n") +
41
- " #{@message}\n Context: #{@context}\n Replacements: #{@replacements}\n References: #{references * ', '}\n")
42
- end
43
- end
44
-
45
- def initialize
46
- path = Dir.tmpdir
47
- download path unless File.exist? "#{path}/#{VERSION}/languagetool-commandline.jar"
48
- @path = path
49
- @p = nil
50
- @reference_line = 0
51
- @errors = []
52
- @unknown_words = []
53
- use_user_glossary "#{path}/#{VERSION}" if File.exist? '.glossary'
54
- end
55
-
56
- def use_user_glossary(path)
57
- resource_path = "#{path}/org/languagetool/resource/en"
58
- system "cp #{resource_path}/added.txt #{resource_path}/added.copy && cp .glossary #{resource_path}/added.txt"
59
- at_exit do
60
- system "cp #{resource_path}/added.copy #{resource_path}/added.txt"
61
- end
62
- end
63
-
64
- def download(path)
65
- system "wget --quiet #{URL} -O /var/tmp/languagetool.zip"
66
- FileUtils.mkdir_p path
67
- system "unzip -qq -u /var/tmp/languagetool.zip -d #{path}"
68
- end
69
-
70
- def start!
71
- @errors = []
72
- @unknown_words = []
73
- @reference_line = 0
74
- Dir.chdir("#{@path}/#{VERSION}/") do
75
- @p = IO.popen('java -jar languagetool-commandline.jar --list-unknown --api --language en-US -', 'r+')
76
- end
77
- end
78
-
79
- def tag(sentences)
80
- output = ''
81
- Dir.chdir("#{@path}/#{VERSION}/") do
82
- p = IO.popen('java -jar languagetool-commandline.jar --taggeronly --api --language en-US -', 'r+')
83
- sentences.each { |sentence| p.write sentence }
84
- p.close_write
85
- line = p.readline
86
- loop do
87
- break if line == "<!--\n"
88
- output << line
89
- line = p.readline
90
- end
91
- p.close
92
- end
93
- output.gsub!(' ', "\n")
94
- output.gsub!(']', "]\n")
95
- output.gsub!("\n\n", "\n")
96
- output
97
- end
98
-
99
- def check_paragraph(paragraph)
100
- start_line = @reference_line
101
- send paragraph
102
- end_line = @reference_line
103
- send "\n\n"
104
- Range.new(start_line, end_line)
105
- end
106
-
107
- def send(sentence)
108
- @reference_line += sentence.count "\n"
109
- @p.write sentence
110
- end
111
-
112
- def parse_errors(result)
113
- doc = REXML::Document.new result
114
- errors = []
115
- doc.elements.each '//error' do |error|
116
- errors.push Error.new(
117
- error.attributes['category'],
118
- error.attributes['context'].strip,
119
- error.attributes['locqualityissuetype'],
120
- error.attributes['msg'],
121
- error.attributes['replacements'],
122
- error.attributes['ruleId'],
123
- error.attributes['fromy'].to_i,
124
- error.attributes['toy'].to_i)
125
- end
126
- errors
127
- end
128
-
129
- def parse_unknown_words(result)
130
- doc = REXML::Document.new result
131
- errors = []
132
- doc.elements.each '//unknown_words/word' do |error|
133
- errors.push error.text
134
- end
135
- errors
136
- end
137
-
138
- def stop!
139
- @p.close_write
140
- errors = ''
141
- line = @p.readline
142
- loop do
143
- break if line == "<!--\n"
144
- errors << line
145
- line = @p.readline
146
- end
147
- @errors = parse_errors errors
148
- @unknown_words = parse_unknown_words errors
149
- @p.close
150
- end
151
- end
152
-
153
- def initialize(no_cache = false)
19
+ def initialize(no_cache = false, ngram = false)
154
20
  path = "~/.gherkin_language/#{LanguageToolProcess::VERSION}/accepted_paragraphs.yml"
155
21
  @settings_path = File.expand_path path
156
22
  @accepted_paragraphs = {}
@@ -162,6 +28,7 @@ class GherkinLanguage
162
28
  @references = {}
163
29
  @line_to_reference = {}
164
30
  @exceptions = []
31
+ @ngram = ngram
165
32
  end
166
33
 
167
34
  def ignore(exception)
@@ -219,7 +86,7 @@ class GherkinLanguage
219
86
 
220
87
  def report
221
88
  return 0 if @references.keys.empty?
222
- language = LanguageToolProcess.new
89
+ language = LanguageToolProcess.new @ngram
223
90
  language.start!
224
91
 
225
92
  @references.keys.each do |sentence|
@@ -294,43 +161,47 @@ class GherkinLanguage
294
161
  background = []
295
162
  input.each do |features|
296
163
  next unless features.key? 'elements'
297
- elements = features['elements']
298
- elements.each do |scenario|
164
+ features['elements'].each do |scenario|
299
165
  next unless scenario.key? 'steps'
300
166
  terms = background.dup
301
167
  if scenario['type'] == 'background'
302
- scenario['steps'].each do |step|
303
- new_terms = [step['keyword'], step['name']].join
304
- new_terms = uncapitalize(new_terms) unless terms.empty?
305
- background.push new_terms
306
- end
168
+ background.push extract_terms_from_scenario(scenario['steps'], terms)
307
169
  next
308
170
  end
309
171
 
310
- scenario['steps'].each do |step|
311
- keyword = step['keyword']
312
- keyword = 'and ' unless background.empty? || keyword != 'Given '
313
- new_terms = [keyword, step['name']].join
314
- new_terms = uncapitalize(new_terms) unless terms.empty?
315
- terms.push new_terms
316
- end
317
- sentence = terms.join ' '
172
+ terms.push extract_terms_from_scenario(scenario['steps'], background)
173
+ sentence = terms.join(' ').strip
318
174
  if scenario.key? 'examples'
319
- prototypes = [sentence.strip]
320
- scenario['examples'].each do |example|
321
- sentences.push example['name'] unless example['name'].empty?
322
- sentences.push example['description'] unless example['description'].empty?
323
- prototypes = prototypes.map { |prototype| expand_outlines(prototype, example) }.flatten
324
- end
325
- sentences += prototypes
175
+ sentences += extract_examples(scenario['examples'], sentence)
326
176
  else
327
- sentences.push sentence.strip
177
+ sentences.push sentence
328
178
  end
329
179
  end
330
180
  end
331
181
  sentences
332
182
  end
333
183
 
184
+ def extract_terms_from_scenario(steps, background)
185
+ steps.map do |step|
186
+ keyword = step['keyword']
187
+ keyword = 'and ' unless background.empty? || keyword != 'Given '
188
+ terms = [keyword, step['name']].join
189
+ terms = uncapitalize(terms) unless background.empty?
190
+ background = terms
191
+ terms
192
+ end.flatten
193
+ end
194
+
195
+ def extract_examples(examples, prototype)
196
+ examples.map do |example|
197
+ sentences = []
198
+ sentences.push example['name'] unless example['name'].empty?
199
+ sentences.push example['description'] unless example['description'].empty?
200
+ sentences += expand_outlines(prototype, example)
201
+ sentences
202
+ end.flatten
203
+ end
204
+
334
205
  def uncapitalize(term)
335
206
  term[0, 1].downcase + term[1..-1]
336
207
  end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ require 'gherkin/formatter/json_formatter'
3
+ require 'gherkin/parser/parser'
4
+ require 'rexml/document'
5
+ require 'stringio'
6
+ require 'multi_json'
7
+ require 'term/ansicolor'
8
+ include Term::ANSIColor
9
+ require 'tmpdir'
10
+ require 'fileutils'
11
+ require 'yaml'
12
+ require 'set'
13
+ require 'digest'
14
+
15
+ # This value entity class represents a language error
16
+ class Error
17
+ attr_accessor :category, :context, :issuetype, :message, :replacements, :rule, :from_y, :to_y
18
+
19
+ def initialize(category, context, issuetype, message, replacements, rule, from_y, to_y)
20
+ @category = category
21
+ @context = context
22
+ @issuetype = issuetype
23
+ @message = message
24
+ @replacements = replacements
25
+ @rule = rule
26
+ @from_y = from_y
27
+ @to_y = to_y
28
+ end
29
+
30
+ def str(references)
31
+ (red("[#{@issuetype}] #{@rule}\n") +
32
+ " #{@message}\n Context: #{@context}\n Replacements: #{@replacements}\n References: #{references * ', '}\n")
33
+ end
34
+ end
@@ -0,0 +1,142 @@
1
+ # encoding: utf-8
2
+ require 'gherkin/formatter/json_formatter'
3
+ require 'gherkin/parser/parser'
4
+ require 'rexml/document'
5
+ require 'stringio'
6
+ require 'multi_json'
7
+ require 'term/ansicolor'
8
+ include Term::ANSIColor
9
+ require 'tmpdir'
10
+ require 'fileutils'
11
+ require 'yaml'
12
+ require 'set'
13
+ require 'digest'
14
+
15
+ # This service class provides access to language tool process.
16
+ class LanguageToolProcess
17
+ attr_accessor :errors, :unknown_words
18
+
19
+ VERSION = 'LanguageTool-3.1'
20
+ URL = "https://www.languagetool.org/download/#{VERSION}.zip"
21
+ NGRAM_VERSION = 'ngrams-en-20150817'
22
+ NGRAM_URL = "https://languagetool.org/download/ngram-data/#{NGRAM_VERSION}.zip"
23
+
24
+ def initialize(ngrams = false)
25
+ path = Dir.tmpdir
26
+ download(path, URL) unless File.exist? "#{path}/#{VERSION}/languagetool-commandline.jar"
27
+ if ngrams
28
+ @ngrams_path = "#{path}/#{NGRAM_VERSION}"
29
+ download("#{@ngrams_path}/en", NGRAM_URL) unless File.exist? @ngrams_path
30
+ end
31
+ @path = path
32
+ @p = nil
33
+ @reference_line = 0
34
+ @errors = []
35
+ @unknown_words = []
36
+ @ngrams = ngrams
37
+ use_user_glossary "#{path}/#{VERSION}" if File.exist? '.glossary'
38
+ end
39
+
40
+ def use_user_glossary(path)
41
+ resource_path = "#{path}/org/languagetool/resource/en"
42
+ system "cp #{resource_path}/added.txt #{resource_path}/added.copy && cp .glossary #{resource_path}/added.txt"
43
+ at_exit do
44
+ system "cp #{resource_path}/added.copy #{resource_path}/added.txt"
45
+ end
46
+ end
47
+
48
+ def download(path, url)
49
+ system "wget --quiet #{url} -O /var/tmp/languagetool.zip"
50
+ FileUtils.mkdir_p path
51
+ system "unzip -qq -u /var/tmp/languagetool.zip -d #{path}"
52
+ system 'rm /var/tmp/languagetool.zip'
53
+ end
54
+
55
+ def start!
56
+ @errors = []
57
+ @unknown_words = []
58
+ @reference_line = 0
59
+ Dir.chdir("#{@path}/#{VERSION}/") do
60
+ command = 'java -jar languagetool-commandline.jar --list-unknown --api --language en-US'
61
+ command += " --languagemodel #{@ngrams_path}" if @ngrams
62
+ @p = IO.popen("#{command} -", 'r+')
63
+ end
64
+ end
65
+
66
+ def tag(sentences)
67
+ output = ''
68
+ Dir.chdir("#{@path}/#{VERSION}/") do
69
+ p = IO.popen('java -jar languagetool-commandline.jar --taggeronly --api --language en-US -', 'r+')
70
+ sentences.each { |sentence| p.write sentence }
71
+ p.close_write
72
+ line = p.readline
73
+ loop do
74
+ break if line == "<!--\n"
75
+ output << line
76
+ line = p.readline
77
+ end
78
+ p.close
79
+ end
80
+ output.gsub!(' ', "\n")
81
+ output.gsub!(']', "]\n")
82
+ output.gsub!("\n\n", "\n")
83
+ output
84
+ end
85
+
86
+ def check_paragraph(paragraph)
87
+ start_line = @reference_line
88
+ send paragraph
89
+ end_line = @reference_line
90
+ send "\n\n"
91
+ Range.new(start_line, end_line)
92
+ end
93
+
94
+ def send(sentence)
95
+ @reference_line += sentence.count "\n"
96
+ @p.write sentence
97
+ end
98
+
99
+ def parse_errors(result)
100
+ doc = REXML::Document.new result
101
+ errors = []
102
+ doc.elements.each '//error' do |error|
103
+ errors.push decode_error error
104
+ end
105
+ errors
106
+ end
107
+
108
+ def decode_error(error)
109
+ Error.new(
110
+ error.attributes['category'],
111
+ error.attributes['context'].strip,
112
+ error.attributes['locqualityissuetype'],
113
+ error.attributes['msg'],
114
+ error.attributes['replacements'],
115
+ error.attributes['ruleId'],
116
+ error.attributes['fromy'].to_i,
117
+ error.attributes['toy'].to_i)
118
+ end
119
+
120
+ def parse_unknown_words(result)
121
+ doc = REXML::Document.new result
122
+ errors = []
123
+ doc.elements.each '//unknown_words/word' do |error|
124
+ errors.push error.text
125
+ end
126
+ errors
127
+ end
128
+
129
+ def stop!
130
+ @p.close_write
131
+ errors = ''
132
+ line = @p.readline
133
+ loop do
134
+ break if line == "<!--\n"
135
+ errors << line
136
+ line = @p.readline
137
+ end
138
+ @errors = parse_errors errors
139
+ @unknown_words = parse_unknown_words errors
140
+ @p.close
141
+ end
142
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gherkin_language
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Rohe
@@ -67,6 +67,7 @@ files:
67
67
  - README.md
68
68
  - Rakefile
69
69
  - bin/gherkin_language
70
+ - features/confused_words.feature
70
71
  - features/correct.feature
71
72
  - features/exception.feature
72
73
  - features/glossary.feature
@@ -76,6 +77,8 @@ files:
76
77
  - features/tag.feature
77
78
  - gherkin_language.gemspec
78
79
  - lib/gherkin_language.rb
80
+ - lib/gherkin_language/error.rb
81
+ - lib/gherkin_language/language_tool_process.rb
79
82
  - test/test_gherkin_language.rb
80
83
  - test/test_gherkin_language_tool.rb
81
84
  homepage: http://github.com/funkwerk/gherkin_language/