ArelテストをMinitest::SpecからActiveSupport::TestCaseへ移行
Arelのテストスイート全体がMinitest::SpecのDSLからActiveSupport::TestCaseベースの記法へ書き直されました。これにより、Rails独自のテスト実行基盤「megatest」へのArael統合を妨げていた最後のブロッカーが解消されます。
背景
#57326では、RailsのテストランナーをMinitest標準から独自実装のmegatestへ移行する取り組みが進んでいます。Active ModelとActive Recordはすでに移行済みでしたが、ArelテストのみがSpec構文を使用していたため、単体での実行を余儀なくされていました。
PR#57326のTODOリストにも「The Arel suite use Minitest::Spec syntax, so it has to be run standalone.」と明記されていた通り、ArelはMinitest::Specに依存しており、megatestがSpec構文をサポートしていないことから、テストスイート全体の統合を妨げるブロッカーとなっていました。本PRはこの制約を取り除くための変換作業です。
技術的な変更
変更の核心は、Arel::Spec(Minitest::Specのサブクラス)からArel::Test(ActiveSupport::TestCaseのサブクラス)への基底クラスの置き換えです。これに伴い、テスト記述スタイルもSpec DSLからTestCase形式へと全面的に移行しています。
describe/itブロックのネスト構造はフラットなtestブロックへ変換され、コンテキスト名はテスト名に接頭辞として折り畳まれています。
変更前(Minitest::Spec):
class AttributeTest < Arel::Spec
describe "#not_eq" do
it "should create a NotEqual node" do
relation = Table.new(:users)
_(relation[:id].not_eq(10)).must_be_kind_of Nodes::NotEqual
end
end
end
変更後(ActiveSupport::TestCase):
class AttributeTest < Arel::Test
test "#not_eq should create a NotEqual node" do
relation = Table.new(:users)
assert_kind_of Nodes::NotEqual, relation[:id].not_eq(10)
end
end
helper.rbにおいても、Minitest::Expectationを拡張していたmust_be_likeメソッドが廃止され、Arel::Assertionsモジュールにassert_likeメソッドが新設されました。このメソッドは文字列の空白を正規化して比較する役割を担っており、SQLの整形差異を吸収します。
変更前(helper.rb):
Minitest::Expectation.class_eval do
def must_be_like(other)
self.class.new(target.gsub(/\s+/, " ").strip, ctx).must_equal other.gsub(/\s+/, " ").strip
end
end
変更後(helper.rb):
module Arel
module Assertions
def assert_like(expected, actual)
assert_equal normalize_like_string(expected), normalize_like_string(actual)
end
private
def normalize_like_string(value)
value.gsub(/\s+/, " ").strip
end
end
end
module Arel
class Test < ActiveSupport::TestCase
include Assertions
# ...
end
end
あわせて、Arel::Specクラス自体もhelper.rbから削除されています。setup/teardownブロックの記述も、before/after(Spec形式)からsetup do/teardown do(TestCase形式)へ統一されました。コレクター系テストでは、ヘルパーメソッドがprivateセクションに整理されるリファクタリングも施されています。
さらに、activerecord/lib/arel/nodes/casted.rbにrequire "active_model/attribute"が追加されました。これはArel::Testベースのテスト環境でActiveModelの自動ロードに頼れなくなるケースへの対応です。
設計判断
describe/itの階層構造をフラットなtestブロックへマッピングする際、コンテキスト情報はテスト名の接頭辞として保持されています。たとえばdescribe "#not_eq" / it "should create..." は test "#not_eq should create..." となり、テスト名から文脈が読み取れる命名規則が維持されています。
assert_likeはExpectation拡張ではなくモジュールとして定義されており、Arel::Testの継承ツリーにincludeで組み込まれています。これにより、Minitest::ExpectationというMinitest内部クラスへの依存が排除され、テストインフラの独立性が高まっています。
まとめ
この変更は機能追加ではなく、テスト記述DSLの統一という基盤整備です。Arel::SpecとMinitest::Expectation拡張を排除し、Arael全テストをActiveSupport::TestCaseへ統一することで、megatestによるRails全体の統合テスト実行という大きな目標に向けて残っていたブロッカーが解消されました。