cucumber-core 16.2.0 → 17.0.0
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 +4 -4
- data/CHANGELOG.md +19 -1
- data/LICENSE +14 -13
- data/lib/cucumber/core/compiler.rb +11 -10
- data/lib/cucumber/core/event.rb +12 -10
- data/lib/cucumber/core/event_bus.rb +1 -1
- data/lib/cucumber/core/events/base.rb +26 -0
- data/lib/cucumber/core/events/envelope.rb +13 -2
- data/lib/cucumber/core/events/gherkin_source_parsed.rb +12 -3
- data/lib/cucumber/core/events/test_case_created.rb +12 -6
- data/lib/cucumber/core/events/test_case_finished.rb +11 -1
- data/lib/cucumber/core/events/test_case_started.rb +12 -3
- data/lib/cucumber/core/events/test_step_created.rb +12 -6
- data/lib/cucumber/core/events/test_step_finished.rb +14 -4
- data/lib/cucumber/core/events/test_step_started.rb +12 -3
- data/lib/cucumber/core/gherkin/document.rb +16 -6
- data/lib/cucumber/core/gherkin/parser.rb +5 -9
- data/lib/cucumber/core/report/summary.rb +2 -2
- data/lib/cucumber/core/test/action/defined.rb +3 -3
- data/lib/cucumber/core/test/action.rb +6 -6
- data/lib/cucumber/core/test/around_hook.rb +4 -4
- data/lib/cucumber/core/test/case.rb +27 -26
- data/lib/cucumber/core/test/data_table.rb +37 -39
- data/lib/cucumber/core/test/doc_string.rb +23 -23
- data/lib/cucumber/core/test/empty_multiline_argument.rb +8 -8
- data/lib/cucumber/core/test/filters/locations_filter.rb +1 -1
- data/lib/cucumber/core/test/filters/name_filter.rb +1 -1
- data/lib/cucumber/core/test/filters/tag_filter.rb +1 -1
- data/lib/cucumber/core/test/filters.rb +3 -3
- data/lib/cucumber/core/test/hook_step.rb +1 -1
- data/lib/cucumber/core/test/location.rb +0 -2
- data/lib/cucumber/core/test/result/ambiguous.rb +41 -0
- data/lib/cucumber/core/test/result/boolean_methods.rb +28 -0
- data/lib/cucumber/core/test/result/duration.rb +33 -0
- data/lib/cucumber/core/test/result/failed.rb +72 -0
- data/lib/cucumber/core/test/result/flaky.rb +21 -0
- data/lib/cucumber/core/test/result/passed.rb +57 -0
- data/lib/cucumber/core/test/result/pending.rb +41 -0
- data/lib/cucumber/core/test/result/raisable.rb +46 -0
- data/lib/cucumber/core/test/result/skipped.rb +41 -0
- data/lib/cucumber/core/test/result/summary.rb +89 -0
- data/lib/cucumber/core/test/result/undefined.rb +41 -0
- data/lib/cucumber/core/test/result/unknown.rb +40 -0
- data/lib/cucumber/core/test/result/unknown_duration.rb +26 -0
- data/lib/cucumber/core/test/result.rb +15 -458
- data/lib/cucumber/core/test/runner.rb +25 -22
- data/lib/cucumber/core/test/step.rb +22 -23
- data/lib/cucumber/core/test/tag.rb +2 -0
- data/lib/cucumber/core/test/timer.rb +1 -1
- data/lib/cucumber/core.rb +6 -5
- metadata +26 -16
- data/lib/cucumber/core/platform.rb +0 -17
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cucumber/messages'
|
|
4
|
+
require 'cucumber/messages/helpers/time_conversion'
|
|
5
|
+
|
|
6
|
+
module Cucumber
|
|
7
|
+
module Core
|
|
8
|
+
module Test
|
|
9
|
+
module Result
|
|
10
|
+
# An object that responds to the description protocol from the results and collects summary information.
|
|
11
|
+
#
|
|
12
|
+
# e.g.
|
|
13
|
+
# summary = Result::Summary.new
|
|
14
|
+
# Result::Passed.new(0).describe_to(summary)
|
|
15
|
+
# puts summary.total_passed
|
|
16
|
+
# => 1
|
|
17
|
+
#
|
|
18
|
+
class Summary
|
|
19
|
+
TYPES = %i[failed ambiguous flaky undefined pending skipped passed unknown].freeze
|
|
20
|
+
|
|
21
|
+
attr_reader :exceptions, :durations
|
|
22
|
+
|
|
23
|
+
def initialize
|
|
24
|
+
@totals = Hash.new { 0 }
|
|
25
|
+
@exceptions = []
|
|
26
|
+
@durations = []
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def method_missing(name, *_args)
|
|
30
|
+
if name =~ /^total_/
|
|
31
|
+
get_total(name)
|
|
32
|
+
else
|
|
33
|
+
increment_total(name)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def respond_to_missing?(*)
|
|
38
|
+
true
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ok?
|
|
42
|
+
TYPES.each do |type|
|
|
43
|
+
return false if get_total(type).positive? && !with_type(type).ok?
|
|
44
|
+
end
|
|
45
|
+
true
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def exception(exception)
|
|
49
|
+
@exceptions << exception
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def duration(duration)
|
|
54
|
+
@durations << duration
|
|
55
|
+
self
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def total(for_status = nil)
|
|
59
|
+
if for_status
|
|
60
|
+
@totals.fetch(for_status, 0)
|
|
61
|
+
else
|
|
62
|
+
@totals.values.reduce(0) { |total, count| total + count }
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def with_type(type)
|
|
67
|
+
Object.const_get("Cucumber::Core::Test::Result::#{type.capitalize}")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def decrement_failed
|
|
71
|
+
@totals[:failed] -= 1
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
def get_total(method_name)
|
|
77
|
+
status = method_name.to_s.gsub('total_', '').to_sym
|
|
78
|
+
@totals.fetch(status, 0)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def increment_total(status)
|
|
82
|
+
@totals[status] += 1
|
|
83
|
+
self
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cucumber/messages'
|
|
4
|
+
require 'cucumber/messages/helpers/time_conversion'
|
|
5
|
+
|
|
6
|
+
module Cucumber
|
|
7
|
+
module Core
|
|
8
|
+
module Test
|
|
9
|
+
module Result
|
|
10
|
+
class Undefined < Raisable
|
|
11
|
+
include BooleanMethods
|
|
12
|
+
|
|
13
|
+
def self.ok?
|
|
14
|
+
false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def describe_to(visitor, *)
|
|
18
|
+
visitor.undefined(*)
|
|
19
|
+
visitor.duration(duration, *)
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_s
|
|
24
|
+
'?'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def to_sym
|
|
28
|
+
:undefined
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_message
|
|
32
|
+
Cucumber::Messages::TestStepResult.new(
|
|
33
|
+
status: Cucumber::Messages::TestStepResultStatus::UNDEFINED,
|
|
34
|
+
duration: duration.to_message_duration
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cucumber/messages'
|
|
4
|
+
require 'cucumber/messages/helpers/time_conversion'
|
|
5
|
+
|
|
6
|
+
module Cucumber
|
|
7
|
+
module Core
|
|
8
|
+
module Test
|
|
9
|
+
module Result
|
|
10
|
+
# Null object for results. Represents the state where we haven't run anything yet
|
|
11
|
+
class Unknown
|
|
12
|
+
include BooleanMethods
|
|
13
|
+
|
|
14
|
+
def self.ok?
|
|
15
|
+
false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def describe_to(_visitor, *_args)
|
|
19
|
+
self
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def with_filtered_backtrace(_filter)
|
|
23
|
+
self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_message
|
|
27
|
+
Cucumber::Messages::TestStepResult.new(
|
|
28
|
+
status: Cucumber::Messages::TestStepResultStatus::UNKNOWN,
|
|
29
|
+
duration: UnknownDuration.new.to_message_duration
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def to_sym
|
|
34
|
+
:unknown
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'cucumber/messages'
|
|
4
|
+
require 'cucumber/messages/helpers/time_conversion'
|
|
5
|
+
|
|
6
|
+
module Cucumber
|
|
7
|
+
module Core
|
|
8
|
+
module Test
|
|
9
|
+
module Result
|
|
10
|
+
class UnknownDuration
|
|
11
|
+
def tap
|
|
12
|
+
self
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def nanoseconds
|
|
16
|
+
raise '#nanoseconds only allowed to be used in #tap block'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_message_duration
|
|
20
|
+
Cucumber::Messages::Duration.new(seconds: 0, nanos: 0)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -3,461 +3,18 @@
|
|
|
3
3
|
require 'cucumber/messages'
|
|
4
4
|
require 'cucumber/messages/helpers/time_conversion'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def self.query_methods(result_type)
|
|
22
|
-
Module.new do
|
|
23
|
-
define_method :to_sym do
|
|
24
|
-
result_type
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
TYPES.each do |possible_result_type|
|
|
28
|
-
define_method("#{possible_result_type}?") do
|
|
29
|
-
possible_result_type == to_sym
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# Null object for results. Represents the state where we haven't run anything yet
|
|
36
|
-
class Unknown
|
|
37
|
-
include Result.query_methods :unknown
|
|
38
|
-
|
|
39
|
-
def describe_to(_visitor, *_args)
|
|
40
|
-
self
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def with_filtered_backtrace(_filter)
|
|
44
|
-
self
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def to_message
|
|
48
|
-
Cucumber::Messages::TestStepResult.new(
|
|
49
|
-
status: Cucumber::Messages::TestStepResultStatus::UNKNOWN,
|
|
50
|
-
duration: UnknownDuration.new.to_message_duration
|
|
51
|
-
)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
class Passed
|
|
56
|
-
include Result.query_methods :passed
|
|
57
|
-
|
|
58
|
-
attr_accessor :duration
|
|
59
|
-
|
|
60
|
-
def self.ok?(*)
|
|
61
|
-
true
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def initialize(duration)
|
|
65
|
-
raise ArgumentError unless duration
|
|
66
|
-
|
|
67
|
-
@duration = duration
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def describe_to(visitor, *)
|
|
71
|
-
visitor.passed(*)
|
|
72
|
-
visitor.duration(duration, *)
|
|
73
|
-
self
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def to_s
|
|
77
|
-
'✓'
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def to_message
|
|
81
|
-
Cucumber::Messages::TestStepResult.new(
|
|
82
|
-
status: Cucumber::Messages::TestStepResultStatus::PASSED,
|
|
83
|
-
duration: duration.to_message_duration
|
|
84
|
-
)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
def ok?(*)
|
|
88
|
-
self.class.ok?
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def with_appended_backtrace(_step)
|
|
92
|
-
self
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def with_filtered_backtrace(_filter)
|
|
96
|
-
self
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
class Failed
|
|
101
|
-
include Result.query_methods :failed
|
|
102
|
-
|
|
103
|
-
attr_reader :duration, :exception
|
|
104
|
-
|
|
105
|
-
def self.ok?(*)
|
|
106
|
-
false
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def initialize(duration, exception)
|
|
110
|
-
raise ArgumentError unless duration
|
|
111
|
-
raise ArgumentError unless exception
|
|
112
|
-
|
|
113
|
-
@duration = duration
|
|
114
|
-
@exception = exception
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def describe_to(visitor, *)
|
|
118
|
-
visitor.failed(*)
|
|
119
|
-
visitor.duration(duration, *)
|
|
120
|
-
visitor.exception(exception, *) if exception
|
|
121
|
-
self
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def to_s
|
|
125
|
-
'✗'
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def to_message
|
|
129
|
-
begin
|
|
130
|
-
message = exception.backtrace.join("\n")
|
|
131
|
-
rescue NoMethodError
|
|
132
|
-
message = ''
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
Cucumber::Messages::TestStepResult.new(
|
|
136
|
-
status: Cucumber::Messages::TestStepResultStatus::FAILED,
|
|
137
|
-
duration: duration.to_message_duration,
|
|
138
|
-
message: message
|
|
139
|
-
)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def ok?(*)
|
|
143
|
-
self.class.ok?
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def with_duration(new_duration)
|
|
147
|
-
self.class.new(new_duration, exception)
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def with_appended_backtrace(step)
|
|
151
|
-
exception.backtrace << step.backtrace_line if step.respond_to?(:backtrace_line)
|
|
152
|
-
self
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def with_filtered_backtrace(filter)
|
|
156
|
-
self.class.new(duration, filter.new(exception.dup).exception)
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
# Flaky is not used directly as an execution result, but is used as a
|
|
161
|
-
# reporting result type for test cases that fails and the passes on
|
|
162
|
-
# retry, therefore only the class method self.ok? is needed.
|
|
163
|
-
class Flaky
|
|
164
|
-
def self.ok?(strict: false)
|
|
165
|
-
!strict
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
# Base class for exceptions that can be raised in a step definition causing the step to have that result.
|
|
170
|
-
class Raisable < StandardError
|
|
171
|
-
attr_reader :message, :duration
|
|
172
|
-
|
|
173
|
-
def initialize(message = '', duration = UnknownDuration.new, backtrace = nil)
|
|
174
|
-
@message = message
|
|
175
|
-
@duration = duration
|
|
176
|
-
super(message)
|
|
177
|
-
set_backtrace(backtrace) if backtrace
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
def with_message(new_message)
|
|
181
|
-
self.class.new(new_message, duration, backtrace)
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
def with_duration(new_duration)
|
|
185
|
-
self.class.new(message, new_duration, backtrace)
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
def with_appended_backtrace(step)
|
|
189
|
-
return self unless step.respond_to?(:backtrace_line)
|
|
190
|
-
|
|
191
|
-
set_backtrace([]) unless backtrace
|
|
192
|
-
backtrace << step.backtrace_line
|
|
193
|
-
self
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
def with_filtered_backtrace(filter)
|
|
197
|
-
return self unless backtrace
|
|
198
|
-
|
|
199
|
-
filter.new(dup).exception
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def ok?(strict: StrictConfiguration.new)
|
|
203
|
-
self.class.ok?(strict: strict.strict?(to_sym))
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
|
|
207
|
-
class Ambiguous < Raisable
|
|
208
|
-
include Result.query_methods :ambiguous
|
|
209
|
-
|
|
210
|
-
def self.ok?(*)
|
|
211
|
-
false
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
def describe_to(visitor, *)
|
|
215
|
-
visitor.ambiguous(*)
|
|
216
|
-
visitor.duration(duration, *)
|
|
217
|
-
self
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
def to_s
|
|
221
|
-
'A'
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
def to_message
|
|
225
|
-
Cucumber::Messages::TestStepResult.new(
|
|
226
|
-
status: Cucumber::Messages::TestStepResultStatus::AMBIGUOUS,
|
|
227
|
-
duration: duration.to_message_duration
|
|
228
|
-
)
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
class Undefined < Raisable
|
|
233
|
-
include Result.query_methods :undefined
|
|
234
|
-
|
|
235
|
-
def self.ok?(strict: false)
|
|
236
|
-
!strict
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
def describe_to(visitor, *)
|
|
240
|
-
visitor.undefined(*)
|
|
241
|
-
visitor.duration(duration, *)
|
|
242
|
-
self
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
def to_s
|
|
246
|
-
'?'
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
def to_message
|
|
250
|
-
Cucumber::Messages::TestStepResult.new(
|
|
251
|
-
status: Cucumber::Messages::TestStepResultStatus::UNDEFINED,
|
|
252
|
-
duration: duration.to_message_duration
|
|
253
|
-
)
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
class Skipped < Raisable
|
|
258
|
-
include Result.query_methods :skipped
|
|
259
|
-
|
|
260
|
-
def self.ok?(*)
|
|
261
|
-
true
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def describe_to(visitor, *)
|
|
265
|
-
visitor.skipped(*)
|
|
266
|
-
visitor.duration(duration, *)
|
|
267
|
-
self
|
|
268
|
-
end
|
|
269
|
-
|
|
270
|
-
def to_s
|
|
271
|
-
'-'
|
|
272
|
-
end
|
|
273
|
-
|
|
274
|
-
def to_message
|
|
275
|
-
Cucumber::Messages::TestStepResult.new(
|
|
276
|
-
status: Cucumber::Messages::TestStepResultStatus::SKIPPED,
|
|
277
|
-
duration: duration.to_message_duration
|
|
278
|
-
)
|
|
279
|
-
end
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
class Pending < Raisable
|
|
283
|
-
include Result.query_methods :pending
|
|
284
|
-
|
|
285
|
-
def self.ok?(strict: false)
|
|
286
|
-
!strict
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
def describe_to(visitor, *)
|
|
290
|
-
visitor.pending(self, *)
|
|
291
|
-
visitor.duration(duration, *)
|
|
292
|
-
self
|
|
293
|
-
end
|
|
294
|
-
|
|
295
|
-
def to_s
|
|
296
|
-
'P'
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
def to_message
|
|
300
|
-
Cucumber::Messages::TestStepResult.new(
|
|
301
|
-
status: Cucumber::Messages::TestStepResultStatus::PENDING,
|
|
302
|
-
duration: duration.to_message_duration
|
|
303
|
-
)
|
|
304
|
-
end
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
# Handles the strict settings for the result types that are
|
|
308
|
-
# affected by the strict options (that is the STRICT_AFFECTED_TYPES).
|
|
309
|
-
class StrictConfiguration
|
|
310
|
-
attr_accessor :settings
|
|
311
|
-
private :settings
|
|
312
|
-
|
|
313
|
-
def initialize(strict_types = [])
|
|
314
|
-
@settings = STRICT_AFFECTED_TYPES.to_h { |t| [t, :default] }
|
|
315
|
-
strict_types.each do |type|
|
|
316
|
-
set_strict(true, type)
|
|
317
|
-
end
|
|
318
|
-
end
|
|
319
|
-
|
|
320
|
-
def strict?(type = nil)
|
|
321
|
-
if type.nil?
|
|
322
|
-
settings.each_value do |value|
|
|
323
|
-
return true if value == true
|
|
324
|
-
end
|
|
325
|
-
false
|
|
326
|
-
else
|
|
327
|
-
return false unless settings.key?(type)
|
|
328
|
-
return false unless set?(type)
|
|
329
|
-
|
|
330
|
-
settings[type]
|
|
331
|
-
end
|
|
332
|
-
end
|
|
333
|
-
|
|
334
|
-
def set_strict(setting, type = nil)
|
|
335
|
-
if type.nil?
|
|
336
|
-
STRICT_AFFECTED_TYPES.each { |type| set_strict(setting, type) }
|
|
337
|
-
else
|
|
338
|
-
settings[type] = setting
|
|
339
|
-
end
|
|
340
|
-
end
|
|
341
|
-
|
|
342
|
-
def merge!(other)
|
|
343
|
-
settings.each_key do |type|
|
|
344
|
-
set_strict(other.strict?(type), type) if other.set?(type)
|
|
345
|
-
end
|
|
346
|
-
self
|
|
347
|
-
end
|
|
348
|
-
|
|
349
|
-
def set?(type)
|
|
350
|
-
settings[type] != :default
|
|
351
|
-
end
|
|
352
|
-
end
|
|
353
|
-
|
|
354
|
-
#
|
|
355
|
-
# An object that responds to the description protocol from the results and collects summary information.
|
|
356
|
-
#
|
|
357
|
-
# e.g.
|
|
358
|
-
# summary = Result::Summary.new
|
|
359
|
-
# Result::Passed.new(0).describe_to(summary)
|
|
360
|
-
# puts summary.total_passed
|
|
361
|
-
# => 1
|
|
362
|
-
#
|
|
363
|
-
class Summary
|
|
364
|
-
attr_reader :exceptions, :durations
|
|
365
|
-
|
|
366
|
-
def initialize
|
|
367
|
-
@totals = Hash.new { 0 }
|
|
368
|
-
@exceptions = []
|
|
369
|
-
@durations = []
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
def method_missing(name, *_args)
|
|
373
|
-
if name =~ /^total_/
|
|
374
|
-
get_total(name)
|
|
375
|
-
else
|
|
376
|
-
increment_total(name)
|
|
377
|
-
end
|
|
378
|
-
end
|
|
379
|
-
|
|
380
|
-
def respond_to_missing?(*)
|
|
381
|
-
true
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
def ok?(strict: StrictConfiguration.new)
|
|
385
|
-
TYPES.each do |type|
|
|
386
|
-
return false if get_total(type).positive? && !Result.ok?(type, strict: strict)
|
|
387
|
-
end
|
|
388
|
-
true
|
|
389
|
-
end
|
|
390
|
-
|
|
391
|
-
def exception(exception)
|
|
392
|
-
@exceptions << exception
|
|
393
|
-
self
|
|
394
|
-
end
|
|
395
|
-
|
|
396
|
-
def duration(duration)
|
|
397
|
-
@durations << duration
|
|
398
|
-
self
|
|
399
|
-
end
|
|
400
|
-
|
|
401
|
-
def total(for_status = nil)
|
|
402
|
-
if for_status
|
|
403
|
-
@totals.fetch(for_status, 0)
|
|
404
|
-
else
|
|
405
|
-
@totals.values.reduce(0) { |total, count| total + count }
|
|
406
|
-
end
|
|
407
|
-
end
|
|
408
|
-
|
|
409
|
-
def decrement_failed
|
|
410
|
-
@totals[:failed] -= 1
|
|
411
|
-
end
|
|
412
|
-
|
|
413
|
-
private
|
|
414
|
-
|
|
415
|
-
def get_total(method_name)
|
|
416
|
-
status = method_name.to_s.gsub('total_', '').to_sym
|
|
417
|
-
@totals.fetch(status, 0)
|
|
418
|
-
end
|
|
419
|
-
|
|
420
|
-
def increment_total(status)
|
|
421
|
-
@totals[status] += 1
|
|
422
|
-
self
|
|
423
|
-
end
|
|
424
|
-
end
|
|
425
|
-
|
|
426
|
-
class Duration
|
|
427
|
-
include Cucumber::Messages::Helpers::TimeConversion
|
|
428
|
-
|
|
429
|
-
attr_reader :nanoseconds
|
|
430
|
-
|
|
431
|
-
def initialize(nanoseconds)
|
|
432
|
-
@nanoseconds = nanoseconds
|
|
433
|
-
end
|
|
434
|
-
|
|
435
|
-
def to_message_duration
|
|
436
|
-
duration_hash = seconds_to_duration(nanoseconds.to_f / NANOSECONDS_PER_SECOND)
|
|
437
|
-
Cucumber::Messages::Duration.new(seconds: duration_hash[:seconds], nanos: duration_hash[:nanos])
|
|
438
|
-
end
|
|
439
|
-
|
|
440
|
-
def seconds_to_duration(seconds_float)
|
|
441
|
-
seconds, second_modulus = seconds_float.divmod(1)
|
|
442
|
-
nanos = second_modulus * NANOSECONDS_PER_SECOND
|
|
443
|
-
{ seconds: seconds, nanos: nanos.to_i }
|
|
444
|
-
end
|
|
445
|
-
end
|
|
446
|
-
|
|
447
|
-
class UnknownDuration
|
|
448
|
-
def tap
|
|
449
|
-
self
|
|
450
|
-
end
|
|
451
|
-
|
|
452
|
-
def nanoseconds
|
|
453
|
-
raise '#nanoseconds only allowed to be used in #tap block'
|
|
454
|
-
end
|
|
455
|
-
|
|
456
|
-
def to_message_duration
|
|
457
|
-
Cucumber::Messages::Duration.new(seconds: 0, nanos: 0)
|
|
458
|
-
end
|
|
459
|
-
end
|
|
460
|
-
end
|
|
461
|
-
end
|
|
462
|
-
end
|
|
463
|
-
end
|
|
6
|
+
require_relative 'result/boolean_methods'
|
|
7
|
+
|
|
8
|
+
require_relative 'result/raisable'
|
|
9
|
+
|
|
10
|
+
require_relative 'result/ambiguous'
|
|
11
|
+
require_relative 'result/duration'
|
|
12
|
+
require_relative 'result/failed'
|
|
13
|
+
require_relative 'result/flaky'
|
|
14
|
+
require_relative 'result/passed'
|
|
15
|
+
require_relative 'result/pending'
|
|
16
|
+
require_relative 'result/summary'
|
|
17
|
+
require_relative 'result/skipped'
|
|
18
|
+
require_relative 'result/undefined'
|
|
19
|
+
require_relative 'result/unknown'
|
|
20
|
+
require_relative 'result/unknown_duration'
|