結論
rescue RSpec::Expectations::ExpectationNotMetError => e
と 明示的 に書けば大丈夫です。もし
rescue => e
とかしている場合は rescue に引っ掛からない、というところでハマりました。
動機
- TurnipFormatter の RSpec 3.0 対応 をしていた
- Turnip は Failed な Example が持つ exception backtrace の末尾に、失敗したシナリオの情報を追記する
- TurnipFormatter はその情報を使ってほげほげいているんだけど、なんか RSpec (正確には
rspec-expectations
) が 3 系になってから ↑ のrescue StandardError => e
に入らなくなっていた
原因
rspec-expectations
が持つマッチャ(よくある expect(1).to be 1
みたいなやつ)が、失敗時には ExpectationNotMetError
を raise していて、これは RSpec 2 および 3 系どちらもで同じ挙動です。
じゃあなんで 3 系でだけ rescue に入ってこなかったかというと ExpectationNotMetError
の定義によるものでした。
RSpec 2.14.5
class ExpectationNotMetError < ::StandardError; end
see v2.14.5/lib/rspec/expectations/errors.rb#L4-L6
RSpec 3.0.3
ExpectationNotMetError = Class.new(::Exception)
see v3.0.3/lib/rspec/expectations.rb#L66)
つまり
- rescue 時にクラス名を省略すると
StandardError => e
と同義になる (たぶん) - RSpec 3 系からは
ExpectationNotMetError
はException
のサブクラス ? になった
というわけでした
まとめ
RSpec のプラグイン系を書いてないと ExpectationNotMetError を捕まえようとは思わないはずなのであまり気にならない仕様変更かなーとは思うけど、ちょっと最初意味わからんかった。