Skip to content

Commit

Permalink
Merge branch 'feature/reduce-test-flakiness'
Browse files Browse the repository at this point in the history
  • Loading branch information
joeyates committed Sep 25, 2023
2 parents c685189 + a2157f3 commit cc7adcc
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 15 deletions.
3 changes: 2 additions & 1 deletion lib/retry_on_error.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
module RetryOnError
def retry_on_error(errors:, limit: 10)
def retry_on_error(errors:, limit: 10, on_error: nil)
tries ||= 1
yield
rescue *errors => e
if tries < limit
message = "#{e}, attempt #{tries} of #{limit}"
Imap::Backup::Logger.logger.debug message
on_error&.call
tries += 1
retry
end
Expand Down
18 changes: 8 additions & 10 deletions spec/features/support/20_test_email_server.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require "retry_on_error"
require_relative "10_server_message_helpers"

class TestEmailServer
include ServerMessageHelpers
include RetryOnError

REQUESTED_ATTRIBUTES = [BODY_ATTRIBUTE, "FLAGS"].freeze

Expand Down Expand Up @@ -49,24 +51,18 @@ def root_folder
end

def folders
# Reconnect if necessary to avoid '#<IOError: closed stream>'
reconnect
imap.list(root_folder, "*")
retry_on_error(errors: [::IOError], limit: 2, on_error: -> { reconnect }) do
imap.list(root_folder, "*")
end
end

def create_folder(folder)
# Reconnect if necessary to avoid '#<IOError: closed stream>'
reconnect

return if folder_exists?(folder)

imap.create(folder)
end

def delete_folder(folder)
# Reconnect if necessary to avoid '#<IOError: closed stream>'
reconnect

return if !folder_exists?(folder)

# N.B. If we are deleting the currently selected folder
Expand Down Expand Up @@ -129,7 +125,9 @@ def fetch_email(folder, uid)
end

def examine(folder)
imap.examine(folder)
retry_on_error(errors: [::IOError], limit: 2, on_error: -> { reconnect }) do
imap.examine(folder)
end
end

def folder_uid_validity(folder)
Expand Down
26 changes: 22 additions & 4 deletions spec/unit/retry_on_error_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ class FooError < StandardError; end

include RetryOnError

def do_stuff(errors:, limit:)
def do_stuff(errors:, limit: 10, on_error: nil)
calls = 0

retry_on_error(errors: errors, limit: limit) do
retry_on_error(errors: errors, limit: limit, on_error: on_error) do
calls += 1
raise FooError if calls < 3
raise FooError, "Failed!" if calls < 3

42
end
Expand All @@ -27,7 +27,25 @@ def do_stuff(errors:, limit:)
it "fails" do
expect do
subject.do_stuff(errors: [Retrier::FooError], limit: 1)
end.to raise_error(Retrier::FooError)
end.to raise_error(Retrier::FooError, /Failed/)
end
end

context "when unexpected errors are raised" do
it "fails" do
expect do
subject.do_stuff(errors: [RuntimeError])
end.to raise_error(Retrier::FooError, /Failed/)
end
end

context "when an :on_error block is passed" do
it "calls the block before retrying" do
on_error_calls = 0
error_proc = -> { on_error_calls += 1 }
subject.do_stuff(errors: [Retrier::FooError], on_error: error_proc)

expect(on_error_calls).to eq(2)
end
end
end
Expand Down

0 comments on commit cc7adcc

Please sign in to comment.