ImmutableString のカスタム真偽文字列オプションとシリアライズ挙動に対するテスト追加
この PR は、ActiveModel::Type::ImmutableString が提供する true:/false: カスタムオプションと、真偽値・数値・シンボルのシリアライズ挙動を検証するテストを追加し、型のドキュメント通りの動作を保証します。
背景
ImmutableString は、値を不変の文字列へ変換する型であり、コンストラクタで true: と false: の文字列オプションを受け取ることが公式に記載されていますが、既存のテストは文字列の凍結(frozenness)だけを確認していました。そのため、カスタム真偽文字列や数値・シンボルのシリアライズが実際に期待通りに動作するかは未検証の状態でした。テストの網羅性を高めることで、開発者がドキュメントどおりにオプションを利用できる保証を提供します。
技術的な変更
activemodel/test/cases/type/immutable_string_test.rb に 3 つのテストケースが追加され、ImmutableString の全体的な変換ロジックを直接検証できるようになりました。
test "custom true and false strings" do
type = Type::ImmutableString.new(true: "aye", false: "nay")
assert_equal "aye", type.cast(true)
assert_equal "nay", type.cast(false)
assert_equal "aye", type.serialize(true)
assert_equal "nay", type.serialize(false)
end
このテストは true:/false: コンストラクタオプションが正しく内部に保持され、cast と serialize の両方で期待した文字列が返ることを確認します。オプションが指定されていない場合のデフォルト動作とは独立して検証できる点が重要です。
test "booleans cast to their default string representations" do
type = Type::ImmutableString.new
assert_equal "t", type.cast(true)
assert_equal "f", type.cast(false)
end
このケースは、オプション未指定時に cast がデフォルトで "t" と "f" を返すことを保証します。ドキュメントに明記されたデフォルト文字列が実装と一致することをテストで明示しています。
test "serialize coerces numerics and symbols to strings" do
type = Type::ImmutableString.new
assert_equal "123", type.serialize(123)
assert_equal "sym", type.serialize(:sym)
end
最後のテストでは、serialize が数値やシンボルを自動的に文字列に変換することを検証します。ImmutableString が value.to_s.freeze に基づく統一的な変換ロジックを持つことを裏付け、型の一貫性を確認できます。
設計判断
テストのみの追加という方針は、実装コードを変更せずに仕様の正確性を保証するという設計姿勢を示しています。既存のインターフェースやデフォルト動作を保持しつつ、オプション指定時の挙動を明示的に検証することで、後方互換性を損なわずに信頼性を高める選択が取られました。このアプローチは、ドキュメントと実装の乖離を防ぐためのベストプラクティスといえます。
まとめ
今回の PR は、ImmutableString のカスタム真偽文字列オプションとシリアライズの多様な入力型に対する挙動をテストで網羅し、ドキュメント通りの動作を保証します。実装は変更せずテストだけを増やすことで、既存コードへの影響を回避しつつ型の信頼性を向上させました。