テストコードでの環境変数参照を定数スタブに置き換え
ActionPackのDebugViewクラスにおいて、環境変数RAILS_HOST_APP_PATHの参照方法を定数経由に変更し、テストコードでは定数スタブを使用するようリファクタリングされました。これにより、テストの独立性と保守性が向上しています。
背景
ActionDispatch::DebugViewは、開発環境でのエラー画面表示を担うクラスで、translate_path_for_editorメソッドがエディタ連携のためにファイルパスを変換する機能を持っています。このメソッドは環境変数RAILS_HOST_APP_PATHを参照してパス変換を行いますが、従来のテストコードではENVを直接操作していました。
テスト実行時に環境変数を変更・復元する処理が各テストに重複しており、テストの独立性とコードの保守性に課題がありました。PR #56875は、環境変数ではなく定数を使用し、定数スタブでテストする方式への移行を実現しています。
技術的な変更
ActionDispatch::DebugViewクラスにHOST_APP_PATH定数が追加され、環境変数の値を保持するようになりました。
変更後:
module ActionDispatch
class DebugView < ActionView::Base
RESCUES_TEMPLATE_PATHS = [File.expand_path("templates", __dir__)]
HOST_APP_PATH = ENV["RAILS_HOST_APP_PATH"]
translate_path_for_editorメソッドでは、ENV["RAILS_HOST_APP_PATH"]への直接アクセスがHOST_APP_PATH定数経由に置き換えられています:
変更前:
def translate_path_for_editor(absolute_path)
path = absolute_path.to_s
host_root = ENV["RAILS_HOST_APP_PATH"].to_s
return path if host_root.empty?
変更後:
def translate_path_for_editor(absolute_path)
path = absolute_path.to_s
return path if HOST_APP_PATH.blank?
テストコードでは、ENVの直接操作からstub_constを使用した定数スタブに変更されました:
変更前:
original_env = ENV["RAILS_HOST_APP_PATH"]
ENV.delete("RAILS_HOST_APP_PATH")
result = debug_view.send(:translate_path_for_editor, path)
assert_equal path, result
ensure
ENV["RAILS_HOST_APP_PATH"] = original_env
変更後:
stub_const(ActionDispatch::DebugView, :HOST_APP_PATH, nil) do
result = debug_view.send(:translate_path_for_editor, path)
assert_equal path, result
end
ensure節による復元処理が不要になり、スタブのスコープがブロック内に明示的に限定されています。3つのテストケースすべてで同様のパターンが適用されており、合計で63行が削除され37行が追加されました。
設計判断
環境変数を定数経由で参照する間接層を導入する設計が採用されました。
テストコードではENVを直接操作する代わりに定数スタブを使用することで、テストの独立性が向上しています。stub_constはブロックスコープ内でのみ有効なため、テスト間の副作用を防ぎ、ensure節による明示的な復元処理が不要になります。この変更により、テストコードの可読性と保守性が改善されています。
プロダクションコードの動作は変更されていません。HOST_APP_PATH定数は初期化時に一度だけ環境変数から値を読み込むため、実行時の環境変数参照コストは従来と同じです。環境変数の値はクラスロード時に固定されますが、Rails アプリケーションの起動後にRAILS_HOST_APP_PATHが変更されることは想定されていないため、この制約は実用上問題になりません。
まとめ
本PRは、テストコードの品質向上を目的としたリファクタリングです。環境変数への直接アクセスを定数経由に変更し、テストでは定数スタブを使用することで、テストの独立性と保守性を高めています。プロダクションコードの動作は変更せず、テストコードの重複を削減し、より明確なスコープ管理を実現しました。