NoRedInk / rspec-retry

retry randomly failing rspec example
MIT License
581 stars 95 forks source link

Instance variables are preserved between tries in controller specs #111

Open jagthedrummer opened 3 years ago

jagthedrummer commented 3 years ago

If you have a controller like this:

class HomeController < ApplicationController
  def index
    @message ||= rand(4)
  end
end

And a controller test like this:

RSpec.describe HomeController, type: :controller do
  describe "GET #index" do
    it "returns a success response" do
      get :index, params: {}, session: {}
      expect(assigns[:message]).to eq(1)
    end
  end
end

And run the test like this:

SPEC_RETRY_RETRY_COUNT=5 rspec spec/controllers/home_controller_spec.rb

If the first try fails then all successive tries will also fail because the @message variable is only set on the first try and the repeated attempts will continue to use the previously set value.

This is unique to controller specs, which I realize are generally not recommended these days. A request spec for the same controller works as expected and a failure on the first run can be "fixed" by a subsequent run since the variable is "cleared out" between each retry.

Here's a repo that demonstrates the problem: https://github.com/jagthedrummer/rspec_retry_test

jagthedrummer commented 3 years ago

After some poking around at rails internals I've found that this will work as a retry callback to clear out instance variables between tries:

  config.retry_callback = proc do |ex|
    if @controller
      @controller.view_assigns.keys.each do |key|
        @controller.remove_instance_variable("@#{key}".to_sym)
      end
    end
  end