由于错误的默认语言环境,我的 Rails 应用程序的规格随机失败
Specs of my Rails app fail randomly because of wrong default locale
有时,我的 Rails 应用程序的某些规格似乎随机失败,因为英语突然不再是默认语言,而是德语:
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"
可以看出,"Access for all" 部分突然变成了 "Zugang für alle"。我在谷歌上搜索了一个解决方案,似乎 I18n.locale
is a global object, so when it's changed in a spec, it persists.
问题并不总是发生,但我可以在指定种子时重现它:rspec --seed 51012
。因此,在其他规范之前(或之后)执行规范似乎确实存在一些问题。
我有一个测试是否可以更改语言环境的功能规范,如下所示:
it 'offers contents in german' do
visit root_path(locale: :de)
expect(page).to have_content 'Willkommen'
end
我怀疑这可能是有问题的规格,当它 运行 早时,它会对其他规格产生影响。
我希望我可以通过将规范中的语言设置回默认值来解决这个问题:
it 'offers contents in german' do
visit root_path(locale: :de)
expect(page).to have_content 'Willkommen'
I18n.locale = :en
end
没用,这个也没用:
it 'offers contents in german' do
visit root_path(locale: :de)
expect(page).to have_content 'Willkommen'
visit root_path(locale: :en)
end
我有点懵了。我该如何调试这种情况,所以我一定会找到问题的根源并修复它(或者至少解决它)?
更新
使用 Dave 的回答 (rspec --bisect
) 我发现了问题。
# 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
根据这些规范的顺序 运行,以下规范的语言环境设置为 :de
或 :en
。
我用 BoraMa 建议的代码片段修复了它:
RSpec.configure do |config|
config.after(:each) { I18n.locale = :en }
end
我还是有点惊讶 RSpec/Rails 不会自己自动执行此操作...
注释掉您怀疑的规格并 运行 rspec --seed 51012
。如果通过,你就知道罪魁祸首了。
如果不是,这看起来像是 rspec --bisect
的工作。做
rspec --seed 51012 --bisect
并让 RSpec 找到重现失败的最小示例集(可能是 2 个)。然后您可以决定如何处理罪魁祸首。
此功能在 RSpec 3.3 中可用,在 RSpec 3.4 中更好。更多信息:https://relishapp.com/rspec/rspec-core/docs/command-line/bisect
有时,我的 Rails 应用程序的某些规格似乎随机失败,因为英语突然不再是默认语言,而是德语:
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"
可以看出,"Access for all" 部分突然变成了 "Zugang für alle"。我在谷歌上搜索了一个解决方案,似乎 I18n.locale
is a global object, so when it's changed in a spec, it persists.
问题并不总是发生,但我可以在指定种子时重现它:rspec --seed 51012
。因此,在其他规范之前(或之后)执行规范似乎确实存在一些问题。
我有一个测试是否可以更改语言环境的功能规范,如下所示:
it 'offers contents in german' do
visit root_path(locale: :de)
expect(page).to have_content 'Willkommen'
end
我怀疑这可能是有问题的规格,当它 运行 早时,它会对其他规格产生影响。
我希望我可以通过将规范中的语言设置回默认值来解决这个问题:
it 'offers contents in german' do
visit root_path(locale: :de)
expect(page).to have_content 'Willkommen'
I18n.locale = :en
end
没用,这个也没用:
it 'offers contents in german' do
visit root_path(locale: :de)
expect(page).to have_content 'Willkommen'
visit root_path(locale: :en)
end
我有点懵了。我该如何调试这种情况,所以我一定会找到问题的根源并修复它(或者至少解决它)?
更新
使用 Dave 的回答 (rspec --bisect
) 我发现了问题。
# 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
根据这些规范的顺序 运行,以下规范的语言环境设置为 :de
或 :en
。
我用 BoraMa 建议的代码片段修复了它:
RSpec.configure do |config|
config.after(:each) { I18n.locale = :en }
end
我还是有点惊讶 RSpec/Rails 不会自己自动执行此操作...
注释掉您怀疑的规格并 运行 rspec --seed 51012
。如果通过,你就知道罪魁祸首了。
如果不是,这看起来像是 rspec --bisect
的工作。做
rspec --seed 51012 --bisect
并让 RSpec 找到重现失败的最小示例集(可能是 2 个)。然后您可以决定如何处理罪魁祸首。
此功能在 RSpec 3.3 中可用,在 RSpec 3.4 中更好。更多信息:https://relishapp.com/rspec/rspec-core/docs/command-line/bisect