cucumber-core 2.0.0 → 3.0.0.pre.2

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: bb172018d9e05188dafca358b06cfe31d5d10575
4
- data.tar.gz: d41a9aa632138309140db42346519eeb349ee322
3
+ metadata.gz: 14ae96e7b157ead29d3bb55f9590dd59abdf2878
4
+ data.tar.gz: 72d1ed6b3b96b8d19c92ffa81d6b1be7ae690a7a
5
5
  SHA512:
6
- metadata.gz: 117f9542f1c84472c5cac771e2eff5284ea9be7f965d40d0e8163b13f8d455e3f1c7654467936fa4da55fd0b4de242eb6677557896239f140da1bd41156f4328
7
- data.tar.gz: 7e911a2e55a093cfd2dd73945d31df73d2504aa5cd88bb1a06f5778d234e5803a039856597595468c408b8ee6b864f6752d575f5753e499a19793dcf3a57166f
6
+ metadata.gz: da7bd878d405691af0f96191da9e1d32caf7802e7d14ef039c206c524ced53c46305c12e74a8ff8362eef619e54cefa606949424609a1f576a1435cb3754879d
7
+ data.tar.gz: b1c03286e6851861e1532547825bc2bd096881acb5140a0cc1717373edbb288620960bf0bb34890459294b020e70bedb0cebd0798a4a3b394a17b0f9e019753d
data/.travis.yml CHANGED
@@ -1,11 +1,20 @@
1
+ language: ruby
1
2
  sudo: false
2
3
 
3
- rvm:
4
- - 2.3.0
5
- - 2.2
6
- - 2.1
7
- - 2.0.0
8
- - jruby-9.0.5.0
4
+ matrix:
5
+ include:
6
+ - rvm: ruby-head
7
+ - rvm: 2.4.1
8
+ - rvm: 2.3.4
9
+ - rvm: 2.2
10
+ - rvm: 2.1
11
+ - rvm: 2.0.0
12
+ - rvm: jruby-9.1.12.0
13
+ env:
14
+ - JRUBY_OPTS="--debug"
15
+ allow_failures:
16
+ - rvm: ruby-head
17
+ fast_finish: true
9
18
 
10
19
  # whitelist
11
20
  branches:
@@ -13,8 +22,6 @@ branches:
13
22
  - master
14
23
 
15
24
  notifications:
16
- email:
17
- - cukes-devs@googlegroups.com
18
25
  webhooks:
19
26
  urls: # gitter
20
27
  - https://webhooks.gitter.im/e/dc010332f9d40fcc21c4
data/HISTORY.md CHANGED
@@ -1,10 +1,41 @@
1
- ## [In Git](https://github.com/cucumber/cucumber-ruby-core/compare/v1.5.0...master)
1
+ ## [In Git](https://github.com/cucumber/cucumber-ruby-core/compare/3.0.0.pre.2...master)
2
2
 
3
3
  ### New Features
4
+ ### Bugfixes
5
+ ### Removed Features
6
+ ### Refactoring
7
+
8
+ ## [3.0.0.pre.2](https://github.com/cucumber/cucumber-ruby-core/compare/v2.0.0...3.0.0.pre.2) (2017-07-26)
9
+
10
+ ### New Features
11
+
12
+ * Add a flaky result type to be used for flaky scenarios ([#141](https://github.com/cucumber/cucumber-ruby-core/pull/141), [cucumber/cucumber-ruby#1044](https://github.com/cucumber/cucumber-ruby/issues/1044) @brasmusson)
13
+ * Make the Summary report able to say if the total result is ok ([#140](https://github.com/cucumber/cucumber-ruby-core/pull/140) @brasmusson)
14
+ * Replay previous events to new subscribers ([#136](https://github.com/cucumber/cucumber-ruby-core/pull/136) @mattwynne)
15
+ * Ruby 2.4.0 compatibility ([#120](https://github.com/cucumber/cucumber-ruby-core/pull/120) @junaruga)
16
+ * Use tag expressions ([#116](https://github.com/cucumber/cucumber-ruby-core/pull/116) @brasmusson)
17
+ * Access example table row data by param name ([#118](https://github.com/cucumber/cucumber-ruby-core/pull/118) @enkessler)
18
+
19
+ ### Bugfixes
20
+
21
+ N/A
22
+
23
+ ### Removed Features
24
+
25
+ N/A
26
+
27
+ ### Refactoring
28
+
29
+ * Travis: jruby-9.1.10.0 ([#130](https://github.com/cucumber/cucumber-ruby-core/pull/130) @olleolleolle)
30
+ * Travis: jruby-9.1.12.0 ([#133](https://github.com/cucumber/cucumber-ruby-core/pull/132) @olleolleolle)
31
+
32
+ ## [2.0.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.5.0...2.0.0)
4
33
 
5
- * Implement equality for test cases ([#111](https://github.com/cucumber/cucumber-ruby-core/pull/111) @mattwynne)
6
- * Implement an event bus (moved from Cucumber-Ruby) ([#106](https://github.com/cucumber/cucumber-ruby-core/pull/106) @mattwynne)
7
- * Use frozen string literals ([#105](https://github.com/cucumber/cucumber-ruby-core/pull/105) @twalpole)
34
+ ### New Features
35
+
36
+ * Implement equality for test cases ([#111](https://github.com/cucumber/cucumber-ruby-core/pull/111) @mattwynne)
37
+ * Implement an event bus (moved from Cucumber-Ruby) ([#106](https://github.com/cucumber/cucumber-ruby-core/pull/106) @mattwynne)
38
+ * Use frozen string literals ([#105](https://github.com/cucumber/cucumber-ruby-core/pull/105) @twalpole)
8
39
 
9
40
  ### Bugfixes
10
41
 
@@ -15,7 +46,11 @@
15
46
 
16
47
  * Remove support for Ruby v1.9.3. ([112](https://github.com/cucumber/cucumber-ruby-core/pull/112) @brasmusson)
17
48
 
18
- ## [v1.5.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.4.0...v1.5.0)
49
+ ### Refactoring
50
+
51
+ N/A
52
+
53
+ ## [1.5.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.4.0...v1.5.0)
19
54
 
20
55
  ### New Features
21
56
 
@@ -25,7 +60,7 @@
25
60
 
26
61
  * Use monotonic time ([#103](https://github.com/cucumber/cucumber-ruby-core/pull/103) @mikz)
27
62
 
28
- ## [v1.4.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.3.1...v1.4.0)
63
+ ## [1.4.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.3.1...v1.4.0)
29
64
 
30
65
  ### New Features
31
66
 
@@ -33,7 +68,7 @@
33
68
 
34
69
  ### Bugfixes
35
70
 
36
- ## [v1.3.1](https://github.com/cucumber/cucumber-ruby-core/compare/v1.3.0...v1.3.1)
71
+ ## [1.3.1](https://github.com/cucumber/cucumber-ruby-core/compare/v1.3.0...v1.3.1)
37
72
 
38
73
  ### New Features
39
74
 
@@ -41,7 +76,7 @@
41
76
 
42
77
  * Speed up location filtering ([#99](https://github.com/cucumber/cucumber-ruby-core/issues/99) @mattwynne @akostadinov @brasmusson)
43
78
 
44
- ## [v1.3.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.2.0...v1.3.0)
79
+ ## [1.3.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.2.0...v1.3.0)
45
80
 
46
81
  ### New Features
47
82
 
@@ -53,7 +88,7 @@
53
88
  * Make sure that `after_test_step` is sent also when a test step is interrupted by (a timeout in) an around hook ([cucumber/cucumber-ruby#909](https://github.com/cucumber/cucumber-ruby/issues/909) @brasmusson)
54
89
  * Improve the check that a test_step quacks like a Cucumber::Core::Test::Step ([95](https://github.com/cucumber/cucumber-ruby-core/issues/95) @brasmusson)
55
90
 
56
- ## [v1.2.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.1.3...v1.2.0)
91
+ ## [1.2.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.1.3...v1.2.0)
57
92
 
58
93
  ### New Features
59
94
 
@@ -65,13 +100,13 @@
65
100
 
66
101
  ### Bugfixes
67
102
 
68
- ## [v1.1.3](https://github.com/cucumber/cucumber-ruby-core/compare/v1.1.2...v1.1.3)
103
+ ## [1.1.3](https://github.com/cucumber/cucumber-ruby-core/compare/v1.1.2...v1.1.3)
69
104
 
70
105
  ### New Features
71
106
 
72
107
  * Added custom `inspect` methods for AST Nodes (@tooky)
73
108
 
74
- ## [v1.1.2](https://github.com/cucumber/cucumber-ruby-core/compare/v1.1.1...v1.1.2)
109
+ ## [1.1.2](https://github.com/cucumber/cucumber-ruby-core/compare/v1.1.1...v1.1.2)
75
110
 
76
111
  ### New Features
77
112
 
@@ -81,24 +116,24 @@
81
116
  * Fail test case if around hook fails (@mattwynne, @tooky)
82
117
  * Expose `Test::Case#around_hooks` (@tooky)
83
118
 
84
- ## [v1.1.1](https://github.com/cucumber/cucumber-ruby-core/compare/v1.1.0...v1.1.1)
119
+ ## [1.1.1](https://github.com/cucumber/cucumber-ruby-core/compare/v1.1.0...v1.1.1)
85
120
 
86
121
 
87
122
  ### New Features
88
123
 
89
124
  * Calculate actual keyword for snippets (@brasmusson)
90
125
 
91
- ### Bugfixes
126
+ ### Bugfixes
92
127
 
93
128
  * Remove keyword from `Test::Case#name` [82](https://github.com/cucumber/cucumber-ruby-core/pull/82) (@richarda)
94
129
 
95
- ## [v1.1.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.0.0...v1.1.0)
130
+ ## [1.1.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.0.0...v1.1.0)
96
131
 
97
132
  ### New features
98
133
 
99
134
  * LocationsFilter now sorts test cases as well as filtering them (@mattwynne)
100
135
 
101
- ## [v1.0.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.0.0.beta.4...v1.0.0)
136
+ ## [1.0.0](https://github.com/cucumber/cucumber-ruby-core/compare/v1.0.0.beta.4...v1.0.0)
102
137
 
103
138
  ### Features Removed
104
139
 
@@ -109,7 +144,7 @@
109
144
 
110
145
  * Added dynamic filter class constructor (@mattwynne)
111
146
 
112
- ## [v1.0.0.beta.4](https://github.com/cucumber/cucumber-ruby-core/compare/v1.0.0.beta.3...v1.0.0.beta.4)
147
+ ## [1.0.0.beta.4](https://github.com/cucumber/cucumber-ruby-core/compare/v1.0.0.beta.3...v1.0.0.beta.4)
113
148
 
114
149
  ### New Features
115
150
 
@@ -122,10 +157,10 @@
122
157
  * Handle empty feature files (#[77](https://github.com/cucumber/cucumber-ruby-core/pull/77), [cucumber/cucumber-ruby#771](https://github.com/cucumber/cucumber-ruby/issues/771) [@brasmusson](https://github.com/brasmusson))
123
158
  * Run after hooks in reverse order (#[69](https://github.com/cucumber/cucumber-ruby-core/pull/69) [@erran](https://github.com/erran))
124
159
 
125
- ## [v1.0.0.beta.3](https://github.com/cucumber/cucumber-ruby-core/compare/v1.0.0.beta.2...v1.0.0.beta.3)
160
+ ## [1.0.0.beta.3](https://github.com/cucumber/cucumber-ruby-core/compare/v1.0.0.beta.2...v1.0.0.beta.3)
126
161
 
127
162
  Changes were not logged.
128
163
 
129
- ## [v1.0.0.beta.2](https://github.com/cucumber/cucumber-ruby-core/compare/v1.0.0.beta.1...v1.0.0.beta.2)
164
+ ## [1.0.0.beta.2](https://github.com/cucumber/cucumber-ruby-core/compare/v1.0.0.beta.1...v1.0.0.beta.2)
130
165
 
131
166
  Changes were not logged.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- #cucumber-core
1
+ # cucumber-core
2
2
 
3
3
  [![Chat with us](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/cucumber/cucumber-ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
4
  [![Build Status](https://secure.travis-ci.org/cucumber/cucumber-ruby-core.svg)](http://travis-ci.org/cucumber/cucumber-ruby-core)
@@ -10,7 +10,7 @@ Cucumber Core is the [inner hexagon](http://alistair.cockburn.us/Hexagonal+archi
10
10
 
11
11
  It contains the core domain logic to execute Cucumber features. It has no user interface, just a Ruby API. If you're interested in how Cucumber works, or in building other tools that work with Gherkin documents, you've come to the right place.
12
12
 
13
- ##An overview
13
+ ## An overview
14
14
 
15
15
  The entry-point is a single method on the module [`Cucumber::Core`](Cucumber/Core.html) called [`#execute`](Cucumber/Core.html#execute-instance_method). Here's what it does:
16
16
 
@@ -21,13 +21,13 @@ The entry-point is a single method on the module [`Cucumber::Core`](Cucumber/Cor
21
21
 
22
22
  We've introduced a number of concepts here, so let's go through them in detail.
23
23
 
24
- ###The AST
24
+ ### The AST
25
25
 
26
26
  The Abstract Syntax Tree or [AST](Cucumber/Core/Ast.html) is an object graph that represents the Gherkin documents you've passed into the core. Things like [Feature](Cucumber/Core/Ast/Feature.html), [Scenario](Cucumber/Core/Ast/Scenario.html) and [ExamplesTable](Cucumber/Core/Ast/ExamplesTable.html).
27
27
 
28
28
  These are immutable value objects.
29
29
 
30
- ###Test cases
30
+ ### Test cases
31
31
 
32
32
  Your gherkin might contain scenarios, as well as examples from tables beneath a scenario outline.
33
33
 
@@ -35,11 +35,11 @@ Test cases represent the general case of both of these. We compile the AST down
35
35
 
36
36
  Test cases and their test steps are also immutable value objects.
37
37
 
38
- ###Filters
38
+ ### Filters
39
39
 
40
40
  Once we have the test cases, and they've been activated by the mappings, you may want to pass them through a filter or two. Filters can be used to do things like activate, sort, replace or remove some of the test cases or their steps before they're executed.
41
41
 
42
- ###Events
42
+ ### Events
43
43
 
44
44
  Events are how you find out what is happening during your test run. As the test cases and steps are executed, the runner emits events to signal what's going on.
45
45
 
@@ -52,7 +52,7 @@ The following events are emitted during a run:
52
52
 
53
53
  That's probably best illustrated with an example.
54
54
 
55
- ##Example
55
+ ## Example
56
56
 
57
57
  Here's an example of how you might use [`Cucumber::Core#execute`](Cucumber/Core#execute-instance_method)
58
58
 
@@ -14,8 +14,9 @@ Gem::Specification.new do |s|
14
14
  s.license = "MIT"
15
15
  s.required_ruby_version = ">= 1.9.3"
16
16
 
17
- s.add_dependency 'gherkin', '~> 4.0'
18
- s.add_dependency 'backports', '~> 3.6'
17
+ s.add_dependency 'gherkin', '>= 4.1.3'
18
+ s.add_dependency 'cucumber-tag_expressions', '>= 1.0.1'
19
+ s.add_dependency 'backports', '>= 3.8.0'
19
20
 
20
21
  s.add_development_dependency 'bundler', '>= 1.3.5'
21
22
  s.add_development_dependency 'rake', '>= 0.9.2'
@@ -82,6 +82,10 @@ module Cucumber
82
82
  other.data == data
83
83
  end
84
84
 
85
+ def [](parameter_name)
86
+ @data[parameter_name]
87
+ end
88
+
85
89
  def values
86
90
  @data.values
87
91
  end
@@ -15,6 +15,7 @@ module Cucumber
15
15
  def initialize(registry = Events.registry)
16
16
  @event_types = registry.freeze
17
17
  @handlers = {}
18
+ @event_queue = []
18
19
  end
19
20
 
20
21
  # Register for an event. The handler proc will be called back with each of the attributes
@@ -24,23 +25,31 @@ module Cucumber
24
25
  validate_handler_and_event_id!(handler, event_id)
25
26
  event_class = event_types[event_id]
26
27
  handlers_for(event_class) << handler
28
+ broadcast_queued_events_to handler, event_class
27
29
  end
28
30
 
29
31
  # Broadcast an event
30
32
  def broadcast(event)
31
33
  raise ArgumentError, "Event type #{event.class} is not registered. Try one of these:\n#{event_types.values.join("\n")}" unless is_registered_type?(event.class)
32
34
  handlers_for(event.class).each { |handler| handler.call(event) }
35
+ @event_queue << event
33
36
  end
34
37
 
35
38
  def method_missing(event_id, *args)
36
39
  event_class = event_types.fetch(event_id) { super }
37
40
  broadcast event_class.new(*args)
38
- rescue NameError => error
39
- raise error, error.message + "\nDid you get the ID of the event wrong? Try one of these:\n#{event_types.keys.join("\n")}", error.backtrace
40
41
  end
41
42
 
42
43
  private
43
44
 
45
+ def broadcast_queued_events_to(handler, event_type)
46
+ @event_queue.select { |event|
47
+ event.class == event_type
48
+ }.each { |event|
49
+ handler.call(event)
50
+ }
51
+ end
52
+
44
53
  def handlers_for(event_class)
45
54
  @handlers[event_class.to_s] ||= []
46
55
  end
@@ -6,16 +6,27 @@ module Cucumber
6
6
  attr_reader :test_cases, :test_steps
7
7
 
8
8
  def initialize(event_bus)
9
+ @previous_test_case = nil
9
10
  @test_cases = Test::Result::Summary.new
10
11
  @test_steps = Test::Result::Summary.new
11
12
  subscribe_to(event_bus)
12
13
  end
13
14
 
15
+ def ok?(be_strict = false)
16
+ test_cases.ok?(be_strict)
17
+ end
18
+
14
19
  private
15
20
 
16
21
  def subscribe_to(event_bus)
17
22
  event_bus.on(:test_case_finished) do |event|
18
- event.result.describe_to test_cases
23
+ if event.test_case != @previous_test_case
24
+ @previous_test_case = event.test_case
25
+ event.result.describe_to test_cases
26
+ elsif event.result.passed?
27
+ test_cases.flaky
28
+ test_cases.decrement_failed
29
+ end
19
30
  end
20
31
  event_bus.on(:test_step_finished) do |event|
21
32
  event.result.describe_to test_steps if is_step?(event.test_step)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'cucumber/core/test/result'
3
+ require 'cucumber/tag_expressions'
3
4
  require 'cucumber/core/gherkin/tag_expression'
4
5
  require 'cucumber/core/ast/location'
5
6
 
@@ -59,7 +60,7 @@ module Cucumber
59
60
  end
60
61
 
61
62
  def match_tags?(*expressions)
62
- Cucumber::Core::Gherkin::TagExpression.new(expressions.flatten).evaluate(tags)
63
+ expressions.flatten.all? { |expression| match_single_tag_expression?(expression) }
63
64
  end
64
65
 
65
66
  def match_name?(name_regexp)
@@ -120,6 +121,18 @@ module Cucumber
120
121
  end.call
121
122
  end
122
123
 
124
+ def match_single_tag_expression?(expression)
125
+ if old_style_tag_expression?(expression)
126
+ Cucumber::Core::Gherkin::TagExpression.new([expression]).evaluate(tags)
127
+ else
128
+ Cucumber::TagExpressions::Parser.new.parse(expression).evaluate(tags.map(&:name))
129
+ end
130
+ end
131
+
132
+ def old_style_tag_expression?(expression)
133
+ expression.include?(',') || expression.include?('~')
134
+ end
135
+
123
136
  class NameBuilder
124
137
  attr_reader :result
125
138
  attr_reader :keyword
@@ -15,7 +15,6 @@ module Cucumber
15
15
  end
16
16
 
17
17
  def done
18
- tag_limits.enforce(test_cases)
19
18
  receiver.done
20
19
  self
21
20
  end
@@ -26,10 +25,6 @@ module Cucumber
26
25
  @test_cases ||= TestCases.new
27
26
  end
28
27
 
29
- def tag_limits
30
- @tag_limits ||= TagLimits.new(filter_expressions)
31
- end
32
-
33
28
  class TestCases
34
29
  attr_reader :test_cases_by_tag_name
35
30
  private :test_cases_by_tag_name
@@ -48,65 +43,6 @@ module Cucumber
48
43
  test_cases_by_tag_name[tag_name]
49
44
  end
50
45
  end
51
-
52
- class TagLimits
53
- TAG_MATCHER = /^
54
- (?:~)? #The tag negation symbol "~". This is optional and not captured.
55
- (?<tag_name>\@\w+) #Captures the tag name including the "@" symbol.
56
- \: #The seperator, ":", between the tag name and the limit.
57
- (?<limit>\d+) #Caputres the limit number.
58
- $/x
59
-
60
- attr_reader :limit_list
61
- private :limit_list
62
- def initialize(filter_expressions)
63
- @limit_list = Array(filter_expressions).flat_map do |raw_expression|
64
- raw_expression.split(/\s*,\s*/)
65
- end.map do |filter_expression|
66
- TAG_MATCHER.match(filter_expression)
67
- end.compact.each_with_object({}) do |matchdata, limit_list|
68
- limit_list[matchdata[:tag_name]] = Integer(matchdata[:limit])
69
- end
70
- end
71
-
72
- def enforce(test_cases)
73
- limit_breaches = limit_list.reduce([]) do |breaches, (tag_name, limit)|
74
- tag_count = test_cases.with_tag_name(tag_name).count
75
- if tag_count > limit
76
- tag_locations = test_cases.with_tag_name(tag_name).map(&:location)
77
- breaches << TagLimitBreach.new(
78
- tag_count,
79
- limit,
80
- tag_name,
81
- tag_locations
82
- )
83
- end
84
- breaches
85
- end
86
- raise TagExcess.new(limit_breaches) if limit_breaches.any?
87
- self
88
- end
89
- end
90
-
91
- TagLimitBreach = Struct.new(
92
- :tag_count,
93
- :tag_limit,
94
- :tag_name,
95
- :tag_locations
96
- ) do
97
-
98
- def message
99
- "#{tag_name} occurred #{tag_count} times, but the limit was set to #{tag_limit}\n " +
100
- tag_locations.map(&:to_s).join("\n ")
101
- end
102
- alias :to_s :message
103
- end
104
-
105
- class TagExcess < StandardError
106
- def initialize(limit_breaches)
107
- super(limit_breaches.map(&:to_s).join("\n"))
108
- end
109
- end
110
46
  end
111
47
  end
112
48
  end
@@ -1,10 +1,17 @@
1
- # encoding: UTF-8
1
+ # encoding: utf-8
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module Cucumber
5
5
  module Core
6
6
  module Test
7
7
  module Result
8
+ TYPES = [:failed, :flaky, :skipped, :undefined, :pending, :passed, :unknown].freeze
9
+
10
+ def self.ok?(type, be_strict = false)
11
+ private
12
+ class_name = type.to_s.slice(0, 1).capitalize + type.to_s.slice(1..-1)
13
+ const_get(class_name).ok?(be_strict)
14
+ end
8
15
 
9
16
  # Defines to_sym on a result class for the given result type
10
17
  #
@@ -16,7 +23,7 @@ module Cucumber
16
23
  result_type
17
24
  end
18
25
 
19
- [:passed, :failed, :undefined, :unknown, :skipped, :pending].each do |possible_result_type|
26
+ TYPES.each do |possible_result_type|
20
27
  define_method("#{possible_result_type}?") do
21
28
  possible_result_type == to_sym
22
29
  end
@@ -41,6 +48,10 @@ module Cucumber
41
48
  include Result.query_methods :passed
42
49
  attr_accessor :duration
43
50
 
51
+ def self.ok?(be_strict = false)
52
+ true
53
+ end
54
+
44
55
  def initialize(duration)
45
56
  raise ArgumentError unless duration
46
57
  @duration = duration
@@ -57,7 +68,7 @@ module Cucumber
57
68
  end
58
69
 
59
70
  def ok?(be_strict = false)
60
- true
71
+ self.class.ok?(be_strict)
61
72
  end
62
73
 
63
74
  def with_appended_backtrace(step)
@@ -73,6 +84,10 @@ module Cucumber
73
84
  include Result.query_methods :failed
74
85
  attr_reader :duration, :exception
75
86
 
87
+ def self.ok?(be_strict = false)
88
+ false
89
+ end
90
+
76
91
  def initialize(duration, exception)
77
92
  raise ArgumentError unless duration
78
93
  raise ArgumentError unless exception
@@ -92,7 +107,7 @@ module Cucumber
92
107
  end
93
108
 
94
109
  def ok?(be_strict = false)
95
- false
110
+ self.class.ok?(be_strict)
96
111
  end
97
112
 
98
113
  def with_duration(new_duration)
@@ -109,7 +124,16 @@ module Cucumber
109
124
  end
110
125
  end
111
126
 
112
- # Base class for exceptions that can be raised in a step defintion causing
127
+ # Flaky is not used directly as an execution result, but is used as a
128
+ # reporting result type for test cases that fails and the passes on
129
+ # retry, therefore only the class method self.ok? is needed.
130
+ class Flaky
131
+ def self.ok?(be_strict = false)
132
+ !be_strict
133
+ end
134
+ end
135
+
136
+ # Base class for exceptions that can be raised in a step definition causing
113
137
  # the step to have that result.
114
138
  class Raisable < StandardError
115
139
  attr_reader :message, :duration
@@ -139,11 +163,19 @@ module Cucumber
139
163
  return self unless backtrace
140
164
  filter.new(dup).exception
141
165
  end
166
+
167
+ def ok?(be_strict = false)
168
+ self.class.ok?(be_strict)
169
+ end
142
170
  end
143
171
 
144
172
  class Undefined < Raisable
145
173
  include Result.query_methods :undefined
146
174
 
175
+ def self.ok?(be_strict = false)
176
+ !be_strict
177
+ end
178
+
147
179
  def describe_to(visitor, *args)
148
180
  visitor.undefined(*args)
149
181
  visitor.duration(duration, *args)
@@ -153,15 +185,15 @@ module Cucumber
153
185
  def to_s
154
186
  "?"
155
187
  end
156
-
157
- def ok?(be_strict = false)
158
- !be_strict
159
- end
160
188
  end
161
189
 
162
190
  class Skipped < Raisable
163
191
  include Result.query_methods :skipped
164
192
 
193
+ def self.ok?(be_strict = false)
194
+ true
195
+ end
196
+
165
197
  def describe_to(visitor, *args)
166
198
  visitor.skipped(*args)
167
199
  visitor.duration(duration, *args)
@@ -171,15 +203,15 @@ module Cucumber
171
203
  def to_s
172
204
  "-"
173
205
  end
174
-
175
- def ok?(be_strict = false)
176
- true
177
- end
178
206
  end
179
207
 
180
208
  class Pending < Raisable
181
209
  include Result.query_methods :pending
182
210
 
211
+ def self.ok?(be_strict = false)
212
+ !be_strict
213
+ end
214
+
183
215
  def describe_to(visitor, *args)
184
216
  visitor.pending(self, *args)
185
217
  visitor.duration(duration, *args)
@@ -189,10 +221,6 @@ module Cucumber
189
221
  def to_s
190
222
  "P"
191
223
  end
192
-
193
- def ok?(be_strict = false)
194
- !be_strict
195
- end
196
224
  end
197
225
 
198
226
  #
@@ -222,6 +250,15 @@ module Cucumber
222
250
  end
223
251
  end
224
252
 
253
+ def ok?(be_strict = false)
254
+ TYPES.each do |type|
255
+ if get_total(type) > 0
256
+ return false unless Result.ok?(type, be_strict)
257
+ end
258
+ end
259
+ true
260
+ end
261
+
225
262
  def exception(exception)
226
263
  @exceptions << exception
227
264
  self
@@ -240,6 +277,10 @@ module Cucumber
240
277
  end
241
278
  end
242
279
 
280
+ def decrement_failed
281
+ @totals[:failed] -= 1
282
+ end
283
+
243
284
  private
244
285
 
245
286
  def get_total(method_name)
@@ -3,7 +3,7 @@ module Cucumber
3
3
  module Core
4
4
  class Version
5
5
  def self.to_s
6
- "2.0.0"
6
+ "3.0.0.pre.2"
7
7
  end
8
8
  end
9
9
  end
data/spec/coverage.rb CHANGED
@@ -7,5 +7,5 @@ if ENV['TRAVIS']
7
7
  formatters << Coveralls::SimpleCov::Formatter
8
8
  end
9
9
 
10
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[*formatters]
10
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(formatters)
11
11
  SimpleCov.start
@@ -77,11 +77,11 @@ module Cucumber
77
77
  expect( doc_string.encoding ).to eq Encoding.find('US-ASCII')
78
78
  end
79
79
 
80
- it 'allows implicit convertion to a String' do
80
+ it 'allows implicit conversion to a String' do
81
81
  expect( 'expected content' ).to include(doc_string)
82
82
  end
83
83
 
84
- it 'allows explicit convertion to a String' do
84
+ it 'allows explicit conversion to a String' do
85
85
  expect( doc_string.to_s ).to eq 'content'
86
86
  end
87
87
 
@@ -75,11 +75,16 @@ module Cucumber::Core::Ast
75
75
  end
76
76
  end
77
77
 
78
- describe 'accesing the values' do
78
+ describe 'accessing the values' do
79
79
  it 'returns the actual row values' do
80
80
  row = ExamplesTable::Row.new({'x' => '1', 'y' => '2'}, 1, location, language, comments)
81
81
  expect( row.values ).to eq ['1', '2']
82
82
  end
83
+
84
+ it "can access a row value by it's parameter name" do
85
+ row = ExamplesTable::Row.new({'x' => '1', 'y' => '2'}, 1, location, language, comments)
86
+ expect( row['x']).to eq '1'
87
+ end
83
88
  end
84
89
 
85
90
  describe 'equality' do
@@ -62,7 +62,7 @@ module Cucumber::Core::Ast
62
62
  expect( matching ).to be_match(precise)
63
63
  end
64
64
 
65
- it "does not match a precise location on a differnt line in the same file" do
65
+ it "does not match a precise location on a different line in the same file" do
66
66
  expect( matching ).not_to be_match(same_file_other_line)
67
67
  end
68
68
 
@@ -136,6 +136,18 @@ module Cucumber
136
136
  expect(handler.received_payload.some_attribute).to eq :some_attribute
137
137
  end
138
138
 
139
+ it "sends events that were broadcast before you subscribed" do
140
+ event_bus.test_event :some_attribute
141
+ event_bus.another_test_event
142
+
143
+ received_payload = nil
144
+ event_bus.on(:test_event) do |event|
145
+ received_payload = event
146
+ end
147
+
148
+ expect(received_payload.some_attribute).to eq(:some_attribute)
149
+ end
150
+
139
151
  end
140
152
 
141
153
  it "will let you inspect the registry" do
@@ -55,6 +55,16 @@ module Cucumber::Core::Report
55
55
  expect( @summary.test_cases.total(:undefined) ).to eq(1)
56
56
  expect( @summary.test_cases.total ).to eq(1)
57
57
  end
58
+
59
+ it "handles flaky test cases" do
60
+ allow(test_case).to receive(:==).and_return(false, true)
61
+ event_bus.send(:test_case_finished, test_case, failed_result)
62
+ event_bus.send(:test_case_finished, test_case, passed_result)
63
+
64
+ expect( @summary.test_cases.total(:failed) ).to eq(0)
65
+ expect( @summary.test_cases.total(:flaky) ).to eq(1)
66
+ expect( @summary.test_cases.total ).to eq(1)
67
+ end
58
68
  end
59
69
 
60
70
  context "test step summary" do
@@ -123,5 +133,41 @@ module Cucumber::Core::Report
123
133
  end
124
134
  end
125
135
  end
136
+
137
+ context "ok? result" do
138
+ let(:test_case) { double }
139
+
140
+ it "passed test case is ok" do
141
+ event_bus.send(:test_case_finished, test_case, passed_result)
142
+
143
+ expect( @summary.ok? ).to eq true
144
+ end
145
+
146
+ it "skipped test case is ok" do
147
+ event_bus.send(:test_case_finished, test_case, skipped_result)
148
+
149
+ expect( @summary.ok? ).to eq true
150
+ end
151
+
152
+ it "failed test case is not ok" do
153
+ event_bus.send(:test_case_finished, test_case, failed_result)
154
+
155
+ expect( @summary.ok? ).to eq false
156
+ end
157
+
158
+ it "pending test case is ok if not strict" do
159
+ event_bus.send(:test_case_finished, test_case, pending_result)
160
+
161
+ expect( @summary.ok? ).to eq true
162
+ expect( @summary.ok?(true) ).to eq false
163
+ end
164
+
165
+ it "undefined test case is ok if not strict" do
166
+ event_bus.send(:test_case_finished, test_case, undefined_result)
167
+
168
+ expect( @summary.ok? ).to eq true
169
+ expect( @summary.ok?(true) ).to eq false
170
+ end
171
+ end
126
172
  end
127
173
  end
@@ -185,6 +185,42 @@ module Cucumber
185
185
  end
186
186
 
187
187
  describe "matching tags" do
188
+ it "matches tags using tag expressions" do
189
+ gherkin = gherkin do
190
+ feature tags: ['@a', '@b'] do
191
+ scenario tags: ['@c'] do
192
+ step
193
+ end
194
+ end
195
+ end
196
+ receiver = double.as_null_object
197
+ expect( receiver ).to receive(:test_case) do |test_case|
198
+ expect( test_case.match_tags?(['@a and @b']) ).to be_truthy
199
+ expect( test_case.match_tags?(['@a or @d']) ).to be_truthy
200
+ expect( test_case.match_tags?(['not @d']) ).to be_truthy
201
+ expect( test_case.match_tags?(['@a and @d']) ).to be_falsy
202
+ end
203
+ compile [gherkin], receiver
204
+ end
205
+
206
+ it "matches handles multiple expressions" do
207
+ gherkin = gherkin do
208
+ feature tags: ['@a', '@b'] do
209
+ scenario tags: ['@c'] do
210
+ step
211
+ end
212
+ end
213
+ end
214
+ receiver = double.as_null_object
215
+ expect( receiver ).to receive(:test_case) do |test_case|
216
+ expect( test_case.match_tags?(['@a and @b', 'not @d']) ).to be_truthy
217
+ expect( test_case.match_tags?(['@a and @b', 'not @c']) ).to be_falsy
218
+ end
219
+ compile [gherkin], receiver
220
+ end
221
+ end
222
+
223
+ describe "matching tags (old style)" do
188
224
  it "matches boolean expressions of tags" do
189
225
  gherkin = gherkin do
190
226
  feature tags: ['@a', '@b'] do
@@ -195,7 +231,25 @@ module Cucumber
195
231
  end
196
232
  receiver = double.as_null_object
197
233
  expect( receiver ).to receive(:test_case) do |test_case|
198
- expect( test_case.match_tags?('@a') ).to be_truthy
234
+ expect( test_case.match_tags?(['@a', '@b']) ).to be_truthy
235
+ expect( test_case.match_tags?(['@a, @d']) ).to be_truthy
236
+ expect( test_case.match_tags?(['~@d']) ).to be_truthy
237
+ expect( test_case.match_tags?(['@a', '@d']) ).to be_falsy
238
+ end
239
+ compile [gherkin], receiver
240
+ end
241
+
242
+ it "handles mixing old and new style expressions" do
243
+ gherkin = gherkin do
244
+ feature tags: ['@a', '@b'] do
245
+ scenario tags: ['@c'] do
246
+ step
247
+ end
248
+ end
249
+ end
250
+ receiver = double.as_null_object
251
+ expect( receiver ).to receive(:test_case) do |test_case|
252
+ expect( test_case.match_tags?(['@a and @b', '~@d']) ).to be_truthy
199
253
  end
200
254
  compile [gherkin], receiver
201
255
  end
@@ -46,6 +46,7 @@ module Cucumber::Core::Test
46
46
  specify { expect( result ).not_to be_undefined }
47
47
  specify { expect( result ).not_to be_unknown }
48
48
  specify { expect( result ).not_to be_skipped }
49
+ specify { expect( result ).not_to be_flaky }
49
50
 
50
51
  specify { expect( result ).to be_ok }
51
52
  specify { expect( result.ok?(false) ).to be_truthy }
@@ -105,6 +106,7 @@ module Cucumber::Core::Test
105
106
  specify { expect( result ).not_to be_undefined }
106
107
  specify { expect( result ).not_to be_unknown }
107
108
  specify { expect( result ).not_to be_skipped }
109
+ specify { expect( result ).not_to be_flaky }
108
110
 
109
111
  specify { expect( result ).to_not be_ok }
110
112
  specify { expect( result.ok?(false) ).to be_falsey }
@@ -130,6 +132,7 @@ module Cucumber::Core::Test
130
132
  specify { expect( result ).not_to be_undefined }
131
133
  specify { expect( result ).to be_unknown }
132
134
  specify { expect( result ).not_to be_skipped }
135
+ specify { expect( result ).not_to be_flaky }
133
136
  end
134
137
 
135
138
  describe Result::Raisable do
@@ -196,6 +199,7 @@ module Cucumber::Core::Test
196
199
  specify { expect( result ).to be_undefined }
197
200
  specify { expect( result ).not_to be_unknown }
198
201
  specify { expect( result ).not_to be_skipped }
202
+ specify { expect( result ).not_to be_flaky }
199
203
 
200
204
  specify { expect( result ).to be_ok }
201
205
  specify { expect( result.ok?(false) ).to be_truthy }
@@ -218,6 +222,7 @@ module Cucumber::Core::Test
218
222
  specify { expect( result ).not_to be_undefined }
219
223
  specify { expect( result ).not_to be_unknown }
220
224
  specify { expect( result ).to be_skipped }
225
+ specify { expect( result ).not_to be_flaky }
221
226
 
222
227
  specify { expect( result ).to be_ok }
223
228
  specify { expect( result.ok?(false) ).to be_truthy }
@@ -240,6 +245,7 @@ module Cucumber::Core::Test
240
245
  specify { expect( result ).not_to be_undefined }
241
246
  specify { expect( result ).not_to be_unknown }
242
247
  specify { expect( result ).not_to be_skipped }
248
+ specify { expect( result ).not_to be_flaky }
243
249
  specify { expect( result ).to be_pending }
244
250
 
245
251
  specify { expect( result ).to be_ok }
@@ -247,12 +253,18 @@ module Cucumber::Core::Test
247
253
  specify { expect( result.ok?(true) ).to be_falsey }
248
254
  end
249
255
 
256
+ describe Result::Flaky do
257
+ specify { expect( Result::Flaky.ok?(false) ).to be_truthy }
258
+ specify { expect( Result::Flaky.ok?(true) ).to be_falsey }
259
+ end
260
+
250
261
  describe Result::Summary do
251
262
  let(:summary) { Result::Summary.new }
252
263
  let(:failed) { Result::Failed.new(Result::Duration.new(10), exception) }
253
264
  let(:passed) { Result::Passed.new(Result::Duration.new(11)) }
254
265
  let(:skipped) { Result::Skipped.new }
255
266
  let(:unknown) { Result::Unknown.new }
267
+ let(:pending) { Result::Pending.new }
256
268
  let(:undefined) { Result::Undefined.new }
257
269
  let(:exception) { StandardError.new }
258
270
 
@@ -328,6 +340,41 @@ module Cucumber::Core::Test
328
340
  [passed, failed].each { |r| r.describe_to summary }
329
341
  expect( summary.exceptions ).to eq [exception]
330
342
  end
343
+
344
+ context "ok? result" do
345
+ it "passed result is ok" do
346
+ passed.describe_to summary
347
+ expect( summary.ok? ).to be true
348
+ end
349
+
350
+ it "skipped result is ok" do
351
+ skipped.describe_to summary
352
+ expect( summary.ok? ).to be true
353
+ end
354
+
355
+ it "failed result is not ok" do
356
+ failed.describe_to summary
357
+ expect( summary.ok? ).to be false
358
+ end
359
+
360
+ it "pending result is ok if not strict" do
361
+ pending.describe_to summary
362
+ expect( summary.ok? ).to be true
363
+ expect( summary.ok?(true) ).to be false
364
+ end
365
+
366
+ it "undefined result is ok if not strict" do
367
+ undefined.describe_to summary
368
+ expect( summary.ok? ).to be true
369
+ expect( summary.ok?(true) ).to be false
370
+ end
371
+
372
+ it "flaky result is ok if not strict" do
373
+ summary.flaky
374
+ expect( summary.ok? ).to be true
375
+ expect( summary.ok?(true) ).to be false
376
+ end
377
+ end
331
378
  end
332
379
 
333
380
  describe Result::Duration do
@@ -77,127 +77,6 @@ module Cucumber
77
77
 
78
78
  compile [gherkin], visitor, [Cucumber::Core::Test::TagFilter.new(['@a', '@b'])]
79
79
  end
80
-
81
- describe 'with tag filters that have limits' do
82
- let(:visitor) { double.as_null_object }
83
- let(:gherkin_doc) do
84
- gherkin do
85
- feature tags: '@feature' do
86
- scenario tags: '@one @three' do
87
- step
88
- end
89
-
90
- scenario tags: '@one' do
91
- step
92
- end
93
-
94
- scenario_outline do
95
- step '<arg>'
96
-
97
- examples tags: '@three'do
98
- row 'arg'
99
- row 'x'
100
- end
101
- end
102
-
103
- scenario tags: '@ignore' do
104
- step
105
- end
106
- end
107
- end
108
- end
109
-
110
- require 'unindent'
111
- def expect_tag_excess(error_message)
112
- expect {
113
- compile [gherkin_doc], visitor, tag_filters
114
- }.to raise_error(
115
- Cucumber::Core::Test::TagFilter::TagExcess, error_message.unindent.chomp
116
- )
117
- end
118
-
119
- context 'on scenarios' do
120
- let(:tag_filters) {
121
- [ Cucumber::Core::Test::TagFilter.new(['@one:1']) ]
122
- }
123
-
124
- it 'raises a tag excess error with the location of the test cases' do
125
- expect_tag_excess <<-STR
126
- @one occurred 2 times, but the limit was set to 1
127
- features/test.feature:5
128
- features/test.feature:9
129
- STR
130
- end
131
- end
132
-
133
- context 'on scenario outlines' do
134
- let(:tag_filters) {
135
- [ Cucumber::Core::Test::TagFilter.new(['@three:1']) ]
136
- }
137
-
138
- it 'raises a tag excess error with the location of the test cases' do
139
- expect_tag_excess <<-STR
140
- @three occurred 2 times, but the limit was set to 1
141
- features/test.feature:5
142
- features/test.feature:18
143
- STR
144
- end
145
- end
146
-
147
- context 'on a feature with scenarios' do
148
- let(:tag_filters) {
149
- [ Cucumber::Core::Test::TagFilter.new(['@feature:2']) ]
150
- }
151
-
152
- it 'raises a tag excess error with the location of the test cases' do
153
- expect_tag_excess <<-STR
154
- @feature occurred 4 times, but the limit was set to 2
155
- features/test.feature:5
156
- features/test.feature:9
157
- features/test.feature:18
158
- features/test.feature:21
159
- STR
160
- end
161
- end
162
-
163
- context 'with negated tags' do
164
- let(:tag_filters) {
165
- [ Cucumber::Core::Test::TagFilter.new(['~@one:1']) ]
166
- }
167
-
168
- it 'raises a tag excess error with the location of the test cases' do
169
- expect_tag_excess <<-STR
170
- @one occurred 2 times, but the limit was set to 1
171
- features/test.feature:5
172
- features/test.feature:9
173
- STR
174
- end
175
- end
176
-
177
- context 'whith multiple tag limits' do
178
- let(:tag_filters) {
179
- [ Cucumber::Core::Test::TagFilter.new(['@one:1, @three:1', '~@feature:3']) ]
180
- }
181
-
182
- it 'raises a tag excess error with the location of the test cases' do
183
- expect_tag_excess <<-STR
184
- @one occurred 2 times, but the limit was set to 1
185
- features/test.feature:5
186
- features/test.feature:9
187
- @three occurred 2 times, but the limit was set to 1
188
- features/test.feature:5
189
- features/test.feature:18
190
- @feature occurred 4 times, but the limit was set to 3
191
- features/test.feature:5
192
- features/test.feature:9
193
- features/test.feature:18
194
- features/test.feature:21
195
- STR
196
- end
197
- end
198
-
199
- end
200
-
201
80
  end
202
81
 
203
82
  describe "executing a test suite" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cucumber-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.0.0.pre.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aslak Hellesøy
@@ -12,36 +12,50 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2016-09-02 00:00:00.000000000 Z
15
+ date: 2017-07-26 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: gherkin
19
19
  requirement: !ruby/object:Gem::Requirement
20
20
  requirements:
21
- - - "~>"
21
+ - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: '4.0'
23
+ version: 4.1.3
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
27
27
  requirements:
28
- - - "~>"
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ version: 4.1.3
31
+ - !ruby/object:Gem::Dependency
32
+ name: cucumber-tag_expressions
33
+ requirement: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: 1.0.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
29
43
  - !ruby/object:Gem::Version
30
- version: '4.0'
44
+ version: 1.0.1
31
45
  - !ruby/object:Gem::Dependency
32
46
  name: backports
33
47
  requirement: !ruby/object:Gem::Requirement
34
48
  requirements:
35
- - - "~>"
49
+ - - ">="
36
50
  - !ruby/object:Gem::Version
37
- version: '3.6'
51
+ version: 3.8.0
38
52
  type: :runtime
39
53
  prerelease: false
40
54
  version_requirements: !ruby/object:Gem::Requirement
41
55
  requirements:
42
- - - "~>"
56
+ - - ">="
43
57
  - !ruby/object:Gem::Version
44
- version: '3.6'
58
+ version: 3.8.0
45
59
  - !ruby/object:Gem::Dependency
46
60
  name: bundler
47
61
  requirement: !ruby/object:Gem::Requirement
@@ -248,15 +262,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
248
262
  version: 1.9.3
249
263
  required_rubygems_version: !ruby/object:Gem::Requirement
250
264
  requirements:
251
- - - ">="
265
+ - - ">"
252
266
  - !ruby/object:Gem::Version
253
- version: '0'
267
+ version: 1.3.1
254
268
  requirements: []
255
269
  rubyforge_project:
256
- rubygems_version: 2.2.2
270
+ rubygems_version: 2.6.8
257
271
  signing_key:
258
272
  specification_version: 4
259
- summary: cucumber-core-2.0.0
273
+ summary: cucumber-core-3.0.0.pre.2
260
274
  test_files:
261
275
  - spec/capture_warnings.rb
262
276
  - spec/coverage.rb
@@ -286,4 +300,3 @@ test_files:
286
300
  - spec/cucumber/core_spec.rb
287
301
  - spec/readme_spec.rb
288
302
  - spec/report_api_spy.rb
289
- has_rdoc: