Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specs of my Rails app fail randomly because of wrong default locale

From time to time, some specs of my Rails app seem to fail randomly because suddenly English is not the default language anymore, but German:

   expected: "Project test customer - Project test name (Audit, Access for all, 2015-06-15).pdf"
        got: "Project test customer - Project test name (Audit, Zugang für alle, 2015-06-15).pdf"

As one can see, the part "Access for all" suddenly is "Zugang für alle". I googled for a solution and it seems that I18n.locale is a global object, so when it's changed in a spec, it persists.

The problem doesn't always occur, but I can reproduce it when specifying a seed like this: rspec --seed 51012. So it really seems to be some issue with a spec being executed before (or after) some other spec.

I have a feature spec which tests whether the locale can be changed, like this:

it 'offers contents in german' do
  visit root_path(locale: :de)

  expect(page).to have_content 'Willkommen'
end

I suspect this could be the problematic spec, and when it's run early, it has impact on other specs.

I hoped that I could solve it by setting the language in the spec back to the default like this:

it 'offers contents in german' do
  visit root_path(locale: :de)

  expect(page).to have_content 'Willkommen'

  I18n.locale = :en
end

Didn't work, also this one didn't:

it 'offers contents in german' do
  visit root_path(locale: :de)

  expect(page).to have_content 'Willkommen'
  visit root_path(locale: :en)
end

I'm a bit clueless now. How could I debug the situation, so I definitely find the source of the problem and fix it (or at least work around it)?

Update

Using Dave's answer (rspec --bisect) I found the problem.

# application_controller_spec.rb
describe ApplicationController do
  controller(ApplicationController) do
    def index
      render text: 'Hello World'
    end
  end

  describe 'locale parameter' do
    it 'is set to english when not available in the request' do
      get :index
      expect(I18n.locale).to eq :en
    end

    it 'can be set through the request' do
      get :index, locale: :de
      expect(I18n.locale).to eq :de
    end
  end
end

Depending on the order that these specs were run, the locale was set to :de or :en for following specs.

I fixed it with BoraMa's suggested code snippet:

RSpec.configure do |config|
  config.after(:each) { I18n.locale = :en }
end

I'm still a bit astonished that RSpec/Rails don't do this on their own automatically...

like image 285
Joshua Muheim Avatar asked Mar 16 '16 15:03

Joshua Muheim


1 Answers

Comment out the spec that you suspect and run rspec --seed 51012. If that passes, you know the culprit.

If not, this looks like a job for rspec --bisect. Do

rspec --seed 51012 --bisect

and let RSpec find the minimal set of examples (probably 2) that reproduce the failure. You can then decide what to do about the culprit.

This feature is available in RSpec 3.3 and better in RSpec 3.4. More here: https://relishapp.com/rspec/rspec-core/docs/command-line/bisect

like image 136
Dave Schweisguth Avatar answered Sep 27 '22 20:09

Dave Schweisguth