gherkin_language 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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/