Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RSpec - how to rescue and retry the test?

We have intermittently failing tests due to Net::ReadTimeout errors.

We have yet to figure out a permanent fix. For right now we want to try rescuing that specific error and re-running the test. Not a ideal solution or true fix but we need something in the short term.

How can we re-run the rspec test that failed? I mean how can the test suite do this automatically for that test?

We can catch the error like this:

# spec/support/capybara.rb
def rescue_net_read_timeout(max_tries = 1, tries = 0, &block)
  yield
rescue Net::ReadTimeout => e
  Rails.logger.error e.message
end

but how do we make it try re-running that test? We want to try re-running the test and then if the re-run passes move on with no error (ideally log it though), else fail for real and consider the test and hence the suite to have failed.

like image 749
Michael Durrant Avatar asked Oct 17 '22 20:10

Michael Durrant


2 Answers

The following method uses the wait gem to retry a test - or a portion of a test, possibly just an assertion. It

def retry_test(&block)
  Wait.new(delay: 0.5, attempts: 10).until do
    begin
      yield    
      true # test passed
    rescue RSpec::Expectations::ExpectationNotMetError => x
      # make sure it failed for the expected reason
      expect(x.to_s).to match /Net::ReadTimeout/
      false # test failed, will retry
    end
  end
end

One can verify why it failed, and report a failure immediately if ever the test failed for another reason.

it 'should get a response' do
  retry_test do
    # The entire test, or just the portion to retry
  end
end
like image 99
philant Avatar answered Oct 21 '22 05:10

philant


I use a ruby gem called rspec-repeat. Out of a few hundred automated tests, we might run into a flaky one here or there and this helps us get past false negatives.

Ideally it's best to continue to diagnose these flaky tests, but this helps alleviate issues in the interim.

Side note, rspec-repeat based off of a another library named rspec-retry, but I find the code base for this one to be tidier and the configuration easier to use.

like image 39
Phil Avatar answered Oct 21 '22 04:10

Phil