Skip to content

Commit 1a37222

Browse files
committed
Add a flaky result type to be used for flaky scenarios.
* The flaky result type should be ok in non-strict mode and not ok in strict mode, so the exit code becomes zero with flaky scenarios in non-strict mode. * Update the Summary report to detect and count flaky scenarios.
1 parent f23f5b6 commit 1a37222

File tree

4 files changed

+49
-2
lines changed

4 files changed

+49
-2
lines changed

lib/cucumber/core/report/summary.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class Summary
66
attr_reader :test_cases, :test_steps
77

88
def initialize(event_bus)
9+
@previous_test_case = nil
910
@test_cases = Test::Result::Summary.new
1011
@test_steps = Test::Result::Summary.new
1112
subscribe_to(event_bus)
@@ -19,7 +20,13 @@ def ok?(be_strict = false)
1920

2021
def subscribe_to(event_bus)
2122
event_bus.on(:test_case_finished) do |event|
22-
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
2330
end
2431
event_bus.on(:test_step_finished) do |event|
2532
event.result.describe_to test_steps if is_step?(event.test_step)

lib/cucumber/core/test/result.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Cucumber
55
module Core
66
module Test
77
module Result
8-
TYPES = [:failed, :skipped, :undefined, :pending, :passed, :unknown].freeze
8+
TYPES = [:failed, :flaky, :skipped, :undefined, :pending, :passed, :unknown].freeze
99

1010
def self.ok?(type, be_strict = false)
1111
private
@@ -124,6 +124,15 @@ def with_filtered_backtrace(filter)
124124
end
125125
end
126126

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+
127136
# Base class for exceptions that can be raised in a step definition causing
128137
# the step to have that result.
129138
class Raisable < StandardError
@@ -268,6 +277,10 @@ def total(for_status = nil)
268277
end
269278
end
270279

280+
def decrement_failed
281+
@totals[:failed] -= 1
282+
end
283+
271284
private
272285

273286
def get_total(method_name)

spec/cucumber/core/report/summary_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ module Cucumber::Core::Report
5555
expect( @summary.test_cases.total(:undefined) ).to eq(1)
5656
expect( @summary.test_cases.total ).to eq(1)
5757
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
5868
end
5969

6070
context "test step summary" do

spec/cucumber/core/test/result_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ module Cucumber::Core::Test
4646
specify { expect( result ).not_to be_undefined }
4747
specify { expect( result ).not_to be_unknown }
4848
specify { expect( result ).not_to be_skipped }
49+
specify { expect( result ).not_to be_flaky }
4950

5051
specify { expect( result ).to be_ok }
5152
specify { expect( result.ok?(false) ).to be_truthy }
@@ -105,6 +106,7 @@ module Cucumber::Core::Test
105106
specify { expect( result ).not_to be_undefined }
106107
specify { expect( result ).not_to be_unknown }
107108
specify { expect( result ).not_to be_skipped }
109+
specify { expect( result ).not_to be_flaky }
108110

109111
specify { expect( result ).to_not be_ok }
110112
specify { expect( result.ok?(false) ).to be_falsey }
@@ -130,6 +132,7 @@ module Cucumber::Core::Test
130132
specify { expect( result ).not_to be_undefined }
131133
specify { expect( result ).to be_unknown }
132134
specify { expect( result ).not_to be_skipped }
135+
specify { expect( result ).not_to be_flaky }
133136
end
134137

135138
describe Result::Raisable do
@@ -196,6 +199,7 @@ module Cucumber::Core::Test
196199
specify { expect( result ).to be_undefined }
197200
specify { expect( result ).not_to be_unknown }
198201
specify { expect( result ).not_to be_skipped }
202+
specify { expect( result ).not_to be_flaky }
199203

200204
specify { expect( result ).to be_ok }
201205
specify { expect( result.ok?(false) ).to be_truthy }
@@ -218,6 +222,7 @@ module Cucumber::Core::Test
218222
specify { expect( result ).not_to be_undefined }
219223
specify { expect( result ).not_to be_unknown }
220224
specify { expect( result ).to be_skipped }
225+
specify { expect( result ).not_to be_flaky }
221226

222227
specify { expect( result ).to be_ok }
223228
specify { expect( result.ok?(false) ).to be_truthy }
@@ -240,13 +245,19 @@ module Cucumber::Core::Test
240245
specify { expect( result ).not_to be_undefined }
241246
specify { expect( result ).not_to be_unknown }
242247
specify { expect( result ).not_to be_skipped }
248+
specify { expect( result ).not_to be_flaky }
243249
specify { expect( result ).to be_pending }
244250

245251
specify { expect( result ).to be_ok }
246252
specify { expect( result.ok?(false) ).to be_truthy }
247253
specify { expect( result.ok?(true) ).to be_falsey }
248254
end
249255

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+
250261
describe Result::Summary do
251262
let(:summary) { Result::Summary.new }
252263
let(:failed) { Result::Failed.new(Result::Duration.new(10), exception) }
@@ -357,6 +368,12 @@ def describe_to(visitor, *args)
357368
expect( summary.ok? ).to be true
358369
expect( summary.ok?(true) ).to be false
359370
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
360377
end
361378
end
362379

0 commit comments

Comments
 (0)