Rails 7.1でのaction_dispatch.show_exceptionsの変更への対応方法

開発ブログ

Rails 7からRails 7.1へ移行するとaction_dispatch.show_exceptionsという設定項目に関連して「DEPRECATION WARNING」が表示されることがあります。これは、この設定項目にRails 7.1で変更があったためです。この記事では、この変更の背景や対応方法についてご説明します。

とりあえず急いで対処する方法

詳細はさておき、Rails 7.1においてaction_dispatch.show_exceptions関連の警告やエラーを消したいという方は、以下のステップをお試し下さい。

ステップ1

config/environments/test.rbconfig.action_dispatch.show_exceptions:rescuableに設定します。bin/rails testを実行して、エラーが出なければそれでOKです。エラーが出てしまった場合はステップ2に進みます。

ステップ2

config.action_dispatch.show_exceptionsの設定値を、元々trueとしていた場合には:allfalseとしていた場合には:noneへと設定し直します。この設定により以前と同じ挙動になります。bin/rails testを実行して問題がないことを確認します。

警告が発生しうる状況

Rails 7からRails 7.1へ移行(アップデート、アップグレード)し、bin/rails testを実行すると以下の警告が表示される場合があります。

DEPRECATION WARNING: Setting action_dispatch.show_exceptions to false is deprecated. Set to :none instead.

これはRuby on Rails 7.1 リリースノートにある通り「config.action_dispatch.show_exceptionstruefalseを設定することを非推奨化」という更新がRails 7.1であったためです。なお、この更新の詳細や対応方法についての公式な情報は対応するpull request (#45867)で確認できます。

Pull request #45867の概要

ポイントはテスト(test)環境を本番(production)環境に近づけつつ、想定外のエラーが発生した場合には詳細情報が得られるようにしたいというところにあります。この目的を達成するために新たに導入されたのが:rescuableであり、この:rescuableが今後デフォルトとなります。

対応方法

まずはRailsガイドの手順に従い、その手順の中にあるbin/rails app:updateコマンドの実行も行います。

次に、config/environments/test.rbconfig.action_dispatch.show_exceptionsを今後のデフォルトとなる:rescuableにしてbin/rails testでテストを実行します。テストの実行に問題が無く、:rescuableの仕様で支障が無い場合はこれでOKです。

設定で:rescuableを選択してテストを実行するとエラーが出るようになってしまうケースとして考えられるのは、テスト内のassert_raisesにおいて引数で指定した例外をキャッチできなくなりテスト失敗となるケースです。:rescuableでは、本番環境が意図的に救出(rescue)しエラーページ(例えば「404 not foundページ」)を表示するいくつかの例外は、テスト環境でも例外のまま上がってはこなくなり、救出されてエラーページのレスポンスが返るようになります。

そこで、:rescuableに合わせてテストを書き換える場合は、救出される例外をassert_raisesする記述を消し、代わりに、適切な(つまり本番環境と同じ)エラーレスポンスが返ってくることを確認するassert_responseの記述を加えると良いでしょう(assert_responseの日本語版Railsガイドの説明はこちら)。具体例を以下に示します。

変更前の例:

  test "something" do
    assert_raises(ActionController::RoutingError) do
      get something_path( @something )
    end
  end

変更後の例:

  test "something" do
    get something_path( @something )
    assert_response :missing
  end

なお、こういったテストの変更をしたくない場合には、config.action_dispatch.show_exceptionsを、元々trueと設定していた場合には:allfalseと設定していた場合には:noneへと設定し直します。この設定により以前と同じ挙動になり、変更なしでテストがこれまでのように通るはずです。

参考情報:pull request #45867の機械翻訳

本件のpull request (#45867)の主要部分を機械翻訳で日本語にしたものを以下に示します。

背景

統合テスト中、アプリケーションが本番環境とできるだけ近い反応を示すことが望ましいです。これにより、アプリケーションの振る舞いが適切に行われているという自信が得られます。

Railsのテストでは、テスト環境と本番環境との間に一つ大きな不一致があります。それは、HTTPリクエスト中に発生した例外(例えばActiveRecord::RecordNotFound)がテスト内で再度発生し、救出されて404レスポンスに変換されるのではなく、再度発生するということです。

config.action_dispatch.show_exceptionsをtrueに設定すると、テスト環境は本番環境のように動作しますが、予期しない内部サーバーエラーが発生した場合、テストは有用なスタックトレースを提示するのではなく、不透明な500レスポンスになってしまいます。これにより、デバッグがより困難になります。

これにより、開発者は高品質な統合テストと失敗時の改善されたデバッグ体験の間で選択を迫られます。

私は、両方を達成できると提案します。

解決策

設定オプションのconfig.action_dispatch.show_exceptionsを、ブール値から3つの値、:all、:rescuable、:noneのいずれかに変更します。:allと:noneの値は、それぞれ以前のtrueとfalseと同じように動作します。以前はtrueだったもの(現在は:all)は、非テスト環境では引き続きデフォルトとなります。

新たに追加された:rescuableの値は、テスト環境の新しいデフォルトとなります。これは、ActionDispatch::ExceptionWrapper.rescue_responsesで定義された救出可能な例外に対してのみ、レスポンス内で例外を表示します。予期しない内部サーバーエラーが発生した場合、エラーの原因となった例外はテスト内で引き続き発生し、有用なスタックトレースと良好なデバッグ体験を提供します。

Rails 7からRails 7.1へ移行に関するその他のTips

Rails 7からRails 7.1へ移行(アップデート、アップグレード)に関する情報は、本件のものも、本件以外のものも含めて、TechTipsの以下のトピックでまとめられていますので、是非ご覧下さい。

rails 7.0からrails 7.1への移行(アップデート、アップグレード)で必要な作業
タイトルとURLをコピーしました