`ActiveSupport::TestCase.around` フックの導入
Active Support のテストケースに around コールバックが追加され、setup と teardown の間を跨いだコンテキスト管理を1つのブロックで記述できるようになりました。これにより、Minitest ベースのプロジェクトでも他のフレームワークと同様の around フックを利用できます。
背景
Minitestには around フックが存在せず、これがプロジェクトの検討段階で代替テストハーネスへの移行を促す要因になることがありました。minitest/minitest#892 では around フックの組み込みが要望されてきましたが、Minitest 本体での実装は行わない方針が示されています。
サードパーティ製の minitest-hooks gem がこのギャップを埋めていましたが、Active Support はすでに ActiveSupport::Callbacks を持っており、Controller・Jobs・Mailers など他のコンポーネントと同じ仕組みで around フックを実装できる下地がありました。Active Support 側でこの機能を提供することで、外部 gem への依存なく、既存のコールバック体系と一貫した形で利用できます。
技術的な変更
ActiveSupport::Testing::SetupAndTeardown に :test コールバックが追加され、around クラスメソッドが実装されました。
activesupport/lib/active_support/testing/setup_and_teardown.rb の define_callbacks 呼び出しに :test が追加されています。
変更前:
klass.define_callbacks :setup, :teardown
変更後:
klass.define_callbacks :setup, :test, :teardown
ClassMethods モジュールに追加された around メソッドは、:test コールバックに :around フェーズとして登録します。また、初回呼び出し時にのみ AroundCallbackSupport モジュールを include する遅延インクルード方式を採用しています。
def around(*args, &block)
set_callback(:test, :around, *args, &block)
include AroundCallbackSupport unless self < AroundCallbackSupport
end
around ブロックはテストクラスのインスタンスとテストケース(ブロック)の2引数を受け取り、以下のように使用します。
class ClientTest < ActiveSupport::TestCase
around do |test_case, block|
Client.with(stubbed: true, &block)
end
end
このコールバックは TestCase#setup コールバック群と TestCase#teardown コールバック群の間で実行されます。また、テストが失敗した場合でも block.call 以降のコードは実行されるため、リソースのクリーンアップを確実に行えます。
設計判断
AroundCallbackSupport の遅延インクルードが採用された点に注目できます。around を呼び出していないテストクラスには AroundCallbackSupport が混入されないため、#send メソッドのオーバーライドなどの副作用が around を使用するクラスにのみ限定されます。テストファイル activesupport/test/testing/around_callback_test.rb にも、around を呼び出していないクラスでは AroundCallbackSupport が祖先チェーンに含まれないことを確認するテストケースが明示的に追加されています。
test "does not override #send" do
assert_not_includes self.class.ancestors, ActiveSupport::Testing::SetupAndTeardown::AroundCallbackSupport
end
また、既存の setup・teardown に新しい独立したコールバックキー :test を追加する方式が選ばれています。これにより、setup・teardown の実行順序は変わらず、around ブロックがその間のフェーズを包む構造が明確に表現されています。
まとめ
本PRは、Active Support が既に持つ Callbacks 基盤を活用して、最小限の変更で around フックを実現した変更です。遅延インクルードによる副作用の局所化と、既存コールバック体系との設計上の一貫性を両立しており、外部 gem なしに Minitest ベースの Rails テストで around フックが利用できるようになりました。