この記事は以下のバージョンにおいて再現する問題です
- spring v1.1.1
- parallel_tests v0.16.10
しばらく前に、Railsのコマンドを高速化するgemのspringの推奨インストール方法が変わった。
多分、Rails 4.1.0から標準になるからだと思うが。
で、今の公式のインストール方法によるとこんな感じ。
gem "spring", group: :development
gem "spring-commands-rspec", group: :development
gem "spring-commands-cucumber", group: :development
$ bundle install
$ bundle exec spring binstub --all
binstubを作ってWrapしておけば、透過的に早くなって楽だよねって感じです。
で、rspecとかcucumberにspringを対応させるgemを入れておけば、この二つもbinstubを作ってくれるのですが、これが問題です。
parallel_testsでrspecの実行コマンドを探すコードがこうなってます。
def determine_executable
cmd = case
when File.exists?("bin/rspec")
"bin/rspec"
when File.file?("script/spec")
"script/spec"
when ParallelTests.bundler_enabled?
cmd = (run("bundle show rspec-core") =~ %r{Could not find gem.*} ? "spec" : "rspec")
"bundle exec #{cmd}"
else
%w[spec rspec].detect{|cmd| system "#{cmd} --version > /dev/null 2>&1" }
end
cmd or raise("Can't find executables rspec or spec")
end
つまり、binstubで作られたコマンドが最初に引っ掛かります。
そうすると、勝手にspring経由でrspecが実行されて環境変数が切り替わらなくなります。
結果、データベースをプロセスごとに切り替えられなくなって、DB競合で死にます。
というわけで、binstubを使う場合は、rspecとかcucumberは外しておいた方が良さそうです。
parallel_testsを使わない場合は便利なんですけどね…。