`--skip-action-mailer`環境でのAuthenticationジェネレータのテスト生成を修正
--skip-action-mailerオプションでRailsアプリを作成した場合、authenticationジェネレータが生成するテストがActionMailer関連の定数やメソッドを参照してエラーになる問題を修正しました。テンプレートにActionMailer::Railtieの定義確認を追加することで、不要なテストの生成を条件分岐で制御します。
背景
--skip-action-mailerでActionMailerを除外した環境でも、authenticationジェネレータはPasswordsControllerのメールテストを生成していました。ActionMailerが存在しない環境で生成されたテストを実行すると、PasswordsMailerの未定義定数エラーや、assert_enqueued_emailsメソッドの未定義エラーが発生します。
具体的には以下の2つのテストケースでエラーが発生します:
-
test_create:PasswordsControllerTest::PasswordsMailerが未定義(NameError) -
test_create_for_an_unknown_user_redirects_but_sends_no_mail:assert_enqueued_emailsが未定義(NoMethodError)
passwords_controller_test.rb.ttテンプレート内のcreateアクション関連テストはすべてメール送信を前提としているため、ActionMailerなしの環境ではそもそも存在しない機能のテストを生成していたことになります。
技術的な変更
ERBテンプレートにActionMailer::Railtieの定義チェックを追加し、メール関連テストを条件付きで生成するよう変更しました。
変更前:
test "new" do
get new_password_path
assert_response :success
end
test "create" do
post passwords_path, params: { email_address: @user.email_address }
...
end
test "create for an unknown user redirects but sends no mail" do
...
assert_enqueued_emails 0 do
...
end
end
test "edit" do
...
end
変更後:
test "new" do
get new_password_path
assert_response :success
end
<%- if defined?(ActionMailer::Railtie) -%>
test "create" do
post passwords_path, params: { email_address: @user.email_address }
...
end
test "create for an unknown user redirects but sends no mail" do
...
assert_enqueued_emails 0 do
...
end
end
<%- end -%>
test "edit" do
...
end
テンプレートエンジンは生成時にActionMailer::Railtieが定義されているかを評価し、定義されていない場合はcreateアクション関連のテストブロック全体をファイルに出力しません。これにより、生成されたテストファイルは環境に応じた内容になります。
あわせてrailties/test/generators/authentication_generator_test.rbのtest_authentication_generator_without_action_mailerテストに検証を追加しています。
assert_file "test/controllers/passwords_controller_test.rb" do |content|
assert_no_match(/assert_enqueued_email/, content)
end
これにより、ActionMailerなし環境でのジェネレータ動作がリグレッションテストで保護されます。
設計判断
生成時の条件分岐をERBのif defined?で行う方式が採用されました。テスト実行時にskipする方式も考えられますが、この変更では「存在しない機能のテスト自体を生成しない」という方針を取っています。ActionMailerが無効な環境ではPasswordsControllerのcreateアクション自体も存在しないため、テストをスキップするのではなく生成しないことが実態に即した設計です。
<%- -%>(ダッシュ付きERBタグ)を使用することで、条件ブロックの前後に余分な空行が出力されず、生成されるテストファイルの整形が保たれます。
まとめ
本PRは、authenticationジェネレータが依存コンポーネントの有無を考慮せずにテストを生成していた問題を、ERBテンプレートの条件分岐で修正したものです。生成コードの品質を「実行して初めてわかる」から「生成時に保証する」方向へ改善するアプローチは、ジェネレータの設計において重要な原則を示しています。