cuke_modeler 1.5.1 → 2.0.0

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
  SHA256:
3
- metadata.gz: 2a3d9a2a79ed92fc6190aa4d8bfd198d319a283af35d7586ba9dd6e11562b108
4
- data.tar.gz: d55ac4e9e29b02999ea13919ad24353e896a07608b854959ded2c2c664608711
3
+ metadata.gz: 92ec631920bf8e2af7095588f0f85bf6f43e109737d39b7b2b92a5e71b00bd82
4
+ data.tar.gz: c8d6abcdf38a6d71a9281c841a60feb0cf839bfa4c13430009ab56458b7d7ac2
5
5
  SHA512:
6
- metadata.gz: 8a6d159ad8a6d3a5dd556cbeb113f973a85dbc4c5cc130d9fef5f6abacf9b37a4cd1fe4bb7b58e75004bd0483ec3ec2a2b6a5b3991f520e906c0a87e34ad8809
7
- data.tar.gz: 8b4e011d5152f35091002dc317da68e3a290cbed5069bba218e3ef41642d3c281554c3e2f4f7ff91ec756c18147864070f270e433cff23c05de430972fba5834
6
+ metadata.gz: a96083807968d997553eb00ab15f1432e89d96527a0d8a814902c1410a87ea11232ff9de904a063782f5efad3aa6a35c6d9ddbd169e3e2bf248cd11c0ccd6710
7
+ data.tar.gz: 111e2d71eb17c5ac1cd4378bc92672eb76ac412dc6943fc29430eeb6aeacda2955f77171347e633e8fa71fef1a803913affb7a0994bb4e6fee6084e75bbdb760
@@ -2,6 +2,9 @@ os:
2
2
  - linux
3
3
  - osx
4
4
 
5
+ # JRuby isn't working on the new default distribution
6
+ dist: trusty
7
+
5
8
  language: ruby
6
9
  rvm:
7
10
  - 1.8.7
@@ -8,6 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
 
9
9
  Nothing yet...
10
10
 
11
+
12
+ ## [2.0.0] - 2019-02-11
13
+
14
+ ### Changed
15
+
16
+ - Step models now include doc strings and tables when determining their equality with other steps. Previously, only the base text of the step was included and the doc string/table was explicitly ignored.
17
+
18
+
11
19
  ## [1.5.1] - 2019-04-14
12
20
 
13
21
  ### Added
@@ -269,7 +277,8 @@ Nothing yet...
269
277
  - Initial release
270
278
 
271
279
 
272
- [Unreleased]: https://github.com/enkessler/cuke_modeler/compare/v1.5.1...HEAD
280
+ [Unreleased]: https://github.com/enkessler/cuke_modeler/compare/v2.0.0...HEAD
281
+ [2.0.0]: https://github.com/enkessler/cuke_modeler/compare/v1.5.1...v2.0.0
273
282
  [1.5.1]: https://github.com/enkessler/cuke_modeler/compare/v1.5.0...v1.5.1
274
283
  [1.5.0]: https://github.com/enkessler/cuke_modeler/compare/v1.4.0...v1.5.0
275
284
  [1.4.0]: https://github.com/enkessler/cuke_modeler/compare/v1.3.0...v1.4.0
@@ -1,4 +1,4 @@
1
- Copyright (c) 2014-2019 Eric Kessler, et al
1
+ Copyright (c) 2014-2020 Eric Kessler, et al
2
2
 
3
3
  MIT License
4
4
 
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # An adapter that can convert the output of version 2.x of the *gherkin* gem into input that is consumable by this gem.
4
5
 
5
6
  class Gherkin2Adapter
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # An adapter that can convert the output of version 3.x of the *gherkin* gem into input that is consumable by this gem.
4
5
 
5
6
  class Gherkin3Adapter
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # An adapter that can convert the output of version 4.x and 5.x of the *gherkin* gem into input that is consumable by this gem.
4
5
 
5
6
  class Gherkin4Adapter
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # An adapter that can convert the output of version 6.x of the *gherkin* gem into input that is consumable by this gem.
4
5
 
5
6
  class Gherkin6Adapter
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # A mix-in module containing methods used by models that contain other models.
4
5
 
5
6
  module Containing
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # A mix-in module containing methods used by models that represent an element that has a description.
4
5
 
5
6
  module Described
@@ -33,9 +33,11 @@ module CukeModeler
33
33
  # Returns *true* if the two steps have the same base text (i.e. minus any keyword,
34
34
  # table, or doc string and *false* otherwise.
35
35
  def ==(other_step)
36
- return false unless other_step.respond_to?(:text)
36
+ return false unless other_step.is_a?(CukeModeler::Step)
37
37
 
38
- text == other_step.text
38
+ text_matches?(other_step) &&
39
+ table_matches?(other_step) &&
40
+ doc_string_matches?(other_step)
39
41
  end
40
42
 
41
43
  # Returns the model objects that belong to this model.
@@ -65,5 +67,32 @@ module CukeModeler
65
67
  parsed_file.first['feature']['elements'].first['steps'].first
66
68
  end
67
69
 
70
+ def text_matches?(other_step)
71
+ text == other_step.text
72
+ end
73
+
74
+ def table_matches?(other_step)
75
+ return false if (!block.is_a?(CukeModeler::Table) || !other_step.block.is_a?(CukeModeler::Table)) && (block.is_a?(CukeModeler::Table) || other_step.block.is_a?(CukeModeler::Table))
76
+ return true unless block.is_a?(CukeModeler::Table) && other_step.block.is_a?(CukeModeler::Table)
77
+
78
+ first_step_values = block.rows.collect { |table_row| table_row.cells.map(&:value) }
79
+ second_step_values = other_step.block.rows.collect { |table_row| table_row.cells.map(&:value) }
80
+
81
+ first_step_values == second_step_values
82
+ end
83
+
84
+ def doc_string_matches?(other_step)
85
+ return false if (!block.is_a?(CukeModeler::DocString) || !other_step.block.is_a?(CukeModeler::DocString)) && (block.is_a?(CukeModeler::DocString) || other_step.block.is_a?(CukeModeler::DocString))
86
+ return true unless block.is_a?(CukeModeler::DocString) && other_step.block.is_a?(CukeModeler::DocString)
87
+
88
+ first_content = block.content
89
+ first_content_type = block.content_type
90
+ second_content = other_step.block.content
91
+ second_content_type = other_step.block.content_type
92
+
93
+ (first_content == second_content) &&
94
+ (first_content_type == second_content_type)
95
+ end
96
+
68
97
  end
69
98
  end
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # A mix-in module containing methods used by models that represent an element that has a name.
4
5
 
5
6
  module Named
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # A mix-in module containing methods used by models that are nested inside
4
5
  # of other models.
5
6
 
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # A mix-in module containing methods used by models that are parsed from source text.
4
5
 
5
6
  module Parsed
@@ -30,6 +30,7 @@ module CukeModeler
30
30
  require 'gherkin/gherkin'
31
31
  require 'cuke_modeler/adapters/gherkin_6_adapter'
32
32
 
33
+ # NOT A PART OF THE PUBLIC API
33
34
  # The method to use for parsing Gherkin text
34
35
  def self.parsing_method(source_text, filename)
35
36
  messages = Gherkin::Gherkin.from_source(filename, source_text, {:default_dialect => CukeModeler::Parsing.dialect}).to_a
@@ -37,6 +38,7 @@ module CukeModeler
37
38
  messages.map(&:to_hash).find { |message| message[:gherkinDocument] }[:gherkinDocument]
38
39
  end
39
40
 
41
+ # NOT A PART OF THE PUBLIC API
40
42
  # The adapter to use when converting an AST to a standard internal shape
41
43
  def self.adapter_class
42
44
  CukeModeler::Gherkin6Adapter
@@ -48,12 +50,14 @@ module CukeModeler
48
50
 
49
51
 
50
52
  # todo - make these methods private?
53
+ # NOT A PART OF THE PUBLIC API
51
54
  # The method to use for parsing Gherkin text
52
55
  # Filename isn't used by this version of Gherkin but keeping the parameter so that the calling method only has to know one method signature
53
56
  def self.parsing_method(source_text, _filename)
54
57
  Gherkin::Parser.new.parse(source_text)
55
58
  end
56
59
 
60
+ # NOT A PART OF THE PUBLIC API
57
61
  # The adapter to use when converting an AST to a standard internal shape
58
62
  def self.adapter_class
59
63
  CukeModeler::Gherkin4Adapter
@@ -64,12 +68,14 @@ module CukeModeler
64
68
  require 'cuke_modeler/adapters/gherkin_3_adapter'
65
69
 
66
70
 
71
+ # NOT A PART OF THE PUBLIC API
67
72
  # The method to use for parsing Gherkin text
68
73
  # Filename isn't used by this version of Gherkin but keeping the parameter so that the calling method only has to know one method signature
69
74
  def self.parsing_method(source_text, _filename)
70
75
  Gherkin::Parser.new.parse(source_text)
71
76
  end
72
77
 
78
+ # NOT A PART OF THE PUBLIC API
73
79
  # The adapter to use when converting an AST to a standard internal shape
74
80
  def self.adapter_class
75
81
  CukeModeler::Gherkin3Adapter
@@ -83,6 +89,7 @@ module CukeModeler
83
89
  require 'cuke_modeler/adapters/gherkin_2_adapter'
84
90
 
85
91
 
92
+ # NOT A PART OF THE PUBLIC API
86
93
  # The method to use for parsing Gherkin text
87
94
  def self.parsing_method(source_text, filename)
88
95
  io = StringIO.new
@@ -93,6 +100,7 @@ module CukeModeler
93
100
  MultiJson.load(io.string)
94
101
  end
95
102
 
103
+ # NOT A PART OF THE PUBLIC API
96
104
  # The adapter to use when converting an AST to a standard internal shape
97
105
  def self.adapter_class
98
106
  CukeModeler::Gherkin2Adapter
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # A mix-in module containing methods used by models that know from which line of
4
5
  # source code they originate.
5
6
 
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # A mix-in module containing methods used by models that represent an element that has steps.
4
5
 
5
6
  module Stepped
@@ -1,5 +1,6 @@
1
1
  module CukeModeler
2
2
 
3
+ # NOT A PART OF THE PUBLIC API
3
4
  # A mix-in module containing methods used by models that represent an element that can be tagged.
4
5
 
5
6
  module Taggable
@@ -1,4 +1,4 @@
1
1
  module CukeModeler
2
2
  # The gem version
3
- VERSION = '1.5.1'
3
+ VERSION = '2.0.0'
4
4
  end
@@ -0,0 +1,25 @@
1
+ Feature: Step comparison
2
+
3
+ Step comparison using `==` is done based on 'significant' properties. Keywords, being completely interchangeable, do not affect step equality.
4
+
5
+
6
+ Scenario: Comparison of steps
7
+ Given a model for the following step:
8
+ """
9
+ Given a step
10
+ """
11
+ And a model for the following step:
12
+ """
13
+ When a step
14
+ """
15
+ And a model for the following step:
16
+ """
17
+ Then a step
18
+ """
19
+ When the models are compared
20
+ Then all of them are equivalent
21
+ But none of the models are equivalent with a model for the following step:
22
+ """
23
+ And a step
24
+ | plus this table |
25
+ """
@@ -1,6 +1,6 @@
1
1
  Feature: Test comparison
2
2
 
3
- Gherkin elements that contain steps (i.e. backgrounds, scenarios, and outlines) can be compared with one another in order to determine equality. Elements are considered equal if the base text of their steps match. That is, the keyword used for the step and any table or doc string that may be associated with that step are ignored for the purposes of comparison.
3
+ Gherkin elements that contain steps (i.e. backgrounds, scenarios, and outlines) can be compared with one another in order to determine equality. Elements are considered equal if their steps match (see step comparison). Properties that do not affect what a test *does* (e.g. name, description, tags) are ignored for the purposes of comparison.
4
4
 
5
5
 
6
6
  Scenario: Comparing tests
@@ -42,3 +42,8 @@ Given(/^a model for the following outline:$/) do |gherkin_text|
42
42
  @models ||= []
43
43
  @models << CukeModeler::Outline.new(gherkin_text)
44
44
  end
45
+
46
+ Given(/^a model for the following step:$/) do |gherkin_text|
47
+ @models ||= []
48
+ @models << CukeModeler::Step.new(gherkin_text)
49
+ end
@@ -166,6 +166,14 @@ But(/^none of the models are equivalent with a model for the following scenario:
166
166
  end
167
167
  end
168
168
 
169
+ But(/^none of the models are equivalent with a model for the following step:$/) do |gherkin_text|
170
+ model = CukeModeler::Step.new(gherkin_text)
171
+
172
+ @models.each do |other_model|
173
+ expect(model == other_model).to_not be true
174
+ end
175
+ end
176
+
169
177
  Then(/^the model returns models for the following comments:$/) do |model_values|
170
178
  model_values = model_values.raw.flatten
171
179
 
@@ -206,46 +206,140 @@ describe 'Step, Integration' do
206
206
 
207
207
  describe 'step comparison' do
208
208
 
209
- it 'is equal to another Step that has the same text' do
210
- source_1 = "#{STEP_KEYWORD} a step"
211
- source_2 = "#{STEP_KEYWORD} a step"
212
- source_3 = "#{STEP_KEYWORD} a different step"
209
+ context 'a step that has text' do
213
210
 
214
- step_1 = clazz.new(source_1)
215
- step_2 = clazz.new(source_2)
216
- step_3 = clazz.new(source_3)
211
+ let(:step_text) { "#{STEP_KEYWORD} a step" }
212
+ let(:base_step) { clazz.new(step_text) }
217
213
 
214
+ context 'compared to a step that has the same text' do
218
215
 
219
- expect(step_1).to eq(step_2)
220
- expect(step_1).to_not eq(step_3)
221
- end
216
+ let(:compared_step) { clazz.new(step_text) }
222
217
 
223
- it 'ignores steps keywords when comparing steps' do
224
- source_1 = "#{GIVEN_KEYWORD} a step"
225
- source_2 = "#{THEN_KEYWORD} a step"
218
+ it 'considers them to be equal' do
219
+ assert_bidirectional_equality(base_step, compared_step)
220
+ end
226
221
 
227
- step_1 = clazz.new(source_1)
228
- step_2 = clazz.new(source_2)
222
+ end
229
223
 
224
+ context 'compared to a step that has different text' do
230
225
 
231
- expect(step_1).to eq(step_2)
232
- end
226
+ let(:compared_step) { clazz.new(step_text + ' plus some more') }
233
227
 
234
- it 'ignores step tables when comparing steps' do
235
- source_1 = "#{STEP_KEYWORD} a step"
236
- source_2 = "#{STEP_KEYWORD} a step\n|with a table|"
228
+ it 'considers them to not be equal' do
229
+ assert_bidirectional_inequality(base_step, compared_step)
230
+ end
237
231
 
238
- step_1 = clazz.new(source_1)
239
- step_2 = clazz.new(source_2)
232
+ end
240
233
 
234
+ context 'compared to a step that has a table' do
241
235
 
242
- expect(step_1).to eq(step_2)
243
- end
236
+ let(:compared_step) { clazz.new(step_text + "\n | foo |") }
237
+
238
+ it 'considers them to not be equal' do
239
+ assert_bidirectional_inequality(base_step, compared_step)
240
+ end
241
+
242
+ end
243
+
244
+ context 'compared to a step that has a doc string' do
245
+
246
+ let(:compared_step) { clazz.new(step_text + "\n \"\"\"\n foo\n\"\"\"") }
247
+
248
+ it 'considers them to not be equal' do
249
+ assert_bidirectional_inequality(base_step, compared_step)
250
+ end
251
+
252
+ end
253
+
254
+
255
+ context 'and has table' do
256
+
257
+ let(:step_text) { "#{STEP_KEYWORD} a step\n | foo |" }
258
+ let(:base_step) { clazz.new(step_text) }
259
+
260
+ context 'compared to a step that has the same table' do
261
+
262
+ let(:compared_step) { clazz.new(step_text) }
263
+
264
+ it 'considers them to be equal' do
265
+ assert_bidirectional_equality(base_step, compared_step)
266
+ end
267
+
268
+ end
269
+
270
+ context 'compared to a step that has a different table' do
244
271
 
245
- it 'ignores step doc strings when comparing steps' do
246
- source_1 = "#{STEP_KEYWORD} a step"
247
- source_2 = "#{STEP_KEYWORD} a step\n\"\"\"\nwith a doc string\n\"\"\""
272
+ let(:compared_step) { clazz.new(step_text + "\n | a different table |") }
248
273
 
274
+ it 'considers them to not be equal' do
275
+ assert_bidirectional_inequality(base_step, compared_step)
276
+ end
277
+
278
+ end
279
+
280
+ end
281
+
282
+
283
+ context 'and has a doc string' do
284
+
285
+ let(:content) { 'foo' }
286
+ let(:base_step) { clazz.new("#{step_text}\n\"\"\"\n#{content}\n\"\"\"") }
287
+
288
+ context 'compared to a step that has the same doc string' do
289
+
290
+ let(:compared_step) { clazz.new("#{step_text}\n\"\"\"\n#{content}\n\"\"\"") }
291
+
292
+ it 'considers them to be equal' do
293
+ assert_bidirectional_equality(base_step, compared_step)
294
+ end
295
+
296
+ end
297
+
298
+ context 'compared to a step that has a different doc string' do
299
+
300
+ let(:compared_step) { clazz.new("#{step_text}\n\"\"\"\n#{content + 'different'}\n\"\"\"") }
301
+
302
+ it 'considers them to not be equal' do
303
+ assert_bidirectional_inequality(base_step, compared_step)
304
+ end
305
+
306
+ end
307
+
308
+ context 'and has a content type' do
309
+
310
+ let(:content_type) { 'foo' }
311
+ let(:base_step) { clazz.new("#{step_text}\n\"\"\" #{content_type}\n#{content}\n\"\"\"") }
312
+
313
+
314
+ context 'compared to a step that has the same content type' do
315
+
316
+ let(:compared_step) { clazz.new("#{step_text}\n\"\"\" #{content_type}\n#{content}\n\"\"\"") }
317
+
318
+ it 'considers them to be equal' do
319
+ assert_bidirectional_equality(base_step, compared_step)
320
+ end
321
+
322
+ end
323
+
324
+ context 'compared to a step that has a different content type' do
325
+
326
+ let(:compared_step) { clazz.new("#{step_text}\n\"\"\" different #{content_type}\n#{content}\n\"\"\"") }
327
+
328
+ it 'considers them to not be equal' do
329
+ assert_bidirectional_inequality(base_step, compared_step)
330
+ end
331
+
332
+ end
333
+
334
+ end
335
+
336
+ end
337
+
338
+ end
339
+
340
+ it 'ignores steps keywords when comparing steps' do
341
+ source_1 = "#{GIVEN_KEYWORD} a step"
342
+ source_2 = "#{THEN_KEYWORD} a step"
249
343
 
250
344
  step_1 = clazz.new(source_1)
251
345
  step_2 = clazz.new(source_2)
@@ -122,4 +122,15 @@ RSpec.configure do |config|
122
122
  end
123
123
  end
124
124
 
125
+
126
+ def assert_bidirectional_equality(base_thing, compared_thing)
127
+ expect(base_thing).to eq(compared_thing)
128
+ expect(compared_thing).to eq(base_thing)
129
+ end
130
+
131
+ def assert_bidirectional_inequality(base_thing, compared_thing)
132
+ expect(base_thing).to_not eq(compared_thing)
133
+ expect(compared_thing).to_not eq(base_thing)
134
+ end
135
+
125
136
  end
@@ -98,7 +98,7 @@ describe 'Step, Unit', :unit_test => true do
98
98
 
99
99
  it 'can gracefully be compared to other types of objects' do
100
100
  # Some common types of object
101
- [1, 'foo', :bar, [], {}].each do |thing|
101
+ [1, 'foo', :bar, [], {}, nil].each do |thing|
102
102
  expect { step == thing }.to_not raise_error
103
103
  expect(step == thing).to be false
104
104
  end
data/todo.txt CHANGED
@@ -5,8 +5,8 @@ Show less boilerplate code in the documentation
5
5
  replace copying raw data during adaptation (all of the Marshal#load/#unload calls) with simply testing that modification never happens in order to increase performance?
6
6
 
7
7
 
8
- document helper modules as not part of the public API
9
8
 
9
+ # todo - add compatibility with newer versions of Gherkin
10
10
  # todo - incorporate cuke_modeler extensions from other projects
11
11
  # todo - add plenty of testing around weird and minimal gherkin text for all models
12
12
  # todo - add support for `Rule` keyword
@@ -22,3 +22,4 @@ replace joined array source text with single string source text/heredocs
22
22
  unit testing around parsing/modeling cases (whitespace, indentation, minimalistic feature elements, etc.)
23
23
  replace "\n" usages with the currently set record separator (i.e "\$" )
24
24
  make sure that all classes and tests are covered and attaches to code coverage
25
+ - make an actual Gherkin 5 adapter (just inherit from the Gherkin 4 adapter)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuke_modeler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Kessler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-04-14 00:00:00.000000000 Z
11
+ date: 2020-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gherkin
@@ -222,6 +222,7 @@ files:
222
222
  - lib/cuke_modeler/stepped.rb
223
223
  - lib/cuke_modeler/taggable.rb
224
224
  - lib/cuke_modeler/version.rb
225
+ - testing/cucumber/features/analysis/step_comparison.feature
225
226
  - testing/cucumber/features/analysis/test_comparison.feature
226
227
  - testing/cucumber/features/modeling/background_modeling.feature
227
228
  - testing/cucumber/features/modeling/background_output.feature