-
-
Save joakimk/2397889 to your computer and use it in GitHub Desktop.
A simple way to retry examples in RSpec using filters and around
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Based on https://gist.github.com/1718985 | |
# Usage: | |
# 1) Put in spec/support/rspec_retries.rb | |
# 2) Call from spec_helper.rb: "RSpec::Retries.setup(config)" | |
# 3) Change around filter to suit your needs. | |
# Example output: | |
# .............. | |
# | |
# spec/requests/something_spec.rb:10: "should do something" failed. | |
# Retrying, attempt 1 of 5. | |
# Retry successful. | |
# | |
# ..... | |
# You need something like this: | |
# SPECS_ARE_NOT_LOCAL = (ENV['USER'] == "jenkins") | |
module RSpec::Retries | |
COUNT = 5 | |
def self.enable_retries? | |
# Only retry certain failures without Spork. I.e. either in CI, or locally | |
# without Spork, typically when running the whole suite for some reason. | |
if Spork.using_spork? | |
false | |
else | |
SPECS_ARE_NOT_LOCAL || ENV['ENABLE_RETRIES'] | |
end | |
end | |
def self.setup(config) | |
config.include RSpec::Retries | |
if enable_retries? | |
config.around(:each, :retry) do |example| | |
run_with_retries(example, COUNT) | |
end | |
config.around(:each, :sphinx) do |example| | |
run_with_retries(example, COUNT) | |
end | |
config.around(:each, :js) do |example| | |
run_with_retries(example, COUNT) | |
end | |
# This is perhaps because run_with_retries calls example.run which probably doesn't include around filters? | |
def config.around(*args) | |
raise "We can't have multiple arounds in this project because of the way retries are implemented." | |
end | |
end | |
end | |
def run_with_retries(example_to_run, retries) | |
retry_header_shown = false | |
retries.times do |t| | |
self.example.instance_variable_set(:@exception, nil) | |
example_to_run.run | |
break unless self.example.exception | |
raise self.example.exception if self.example.exception == Interrupt # Allow exiting with ^C | |
info = "#{self.example.location.gsub(/#{Rails.root}\//, '')}: \"#{self.example.description}\"" | |
attempt = t + 1 | |
Rails.logger.error("DEBUG_LOCKUPS: #{Process.pid} #{info} ATTEMPT: #{attempt}") | |
unless retry_header_shown | |
puts "\n\n#{info} failed." | |
retry_header_shown = true | |
end | |
# We restart sphinx when a test fails that uses it in case thats the problem. | |
# RSpec::ThinkingSphinx.restart_if_started | |
# Clears away let's. | |
# Without this we got errors where factories appeared to create records without ids, which | |
# resulted in errors like "No route matches.... :foo_id=>#<Foo id: nil," | |
self.class.run_after_all_hooks(self) | |
puts "Retrying, attempt #{attempt} of #{retries}.\n" | |
end | |
if e = self.example.exception | |
puts "Retries failed.\n\n" | |
new_exception = e.exception(e.message + " [retried #{retries} times]") | |
new_exception.set_backtrace e.backtrace | |
self.example.instance_variable_set(:@exception, new_exception) | |
elsif retry_header_shown | |
puts "Retry successful.\n\n" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
run_after_all_hooks
seems to have becomerun_after_context_hooks
in Rspec 3.4.