Range#sole に無限末端範囲のテストを追加
Range#sole が無限範囲で例外を投げることを保証するテストが、末端が nil のケース (1..) でも網羅されました。これにより、実装の guard が両方向の無限範囲を正しく検知することが CI で確認できるようになります。
背景
Range#sole は無限範囲に対して Enumerable::SoleItemExpectedError を raise する設計です。既存テストは begin が nil のケース ((..1).sole) のみを検証しており、guard が self.begin.nil? || self.end.nil? の両方を網羅しているか確認できていませんでした。したがって、end が nil の endless range (1..) に対しても同様の例外が発生することを明示的にテストする必要がありました。
今回の PR はテストコードに無限末端ケースを追加するだけで、実装本体には一切変更を加えていません。既存の guard が期待通り機能することを検証し、将来的な実装変更が guard のロジックを破壊しないことを CI が保証できるようにしました。
技術的な変更
activesupport/test/core_ext/range_ext_test.rb の test_sole メソッドに 4 行の追加が行われました。新たに assert_raises が (1..).sole を呼び出し、メッセージ "infinite range '1..' cannot represent a sole item" を期待する形で記述されています。これにより、begin が nil だけでなく end が nil の無限範囲でも SoleItemExpectedError が発生することが自動テストで確認できるようになりました。
@@ -298,5 +298,9 @@ def test_sole
assert_raises(Enumerable::SoleItemExpectedError, match: "infinite range '..1' cannot represent a sole item") do
(..1).sole
end
+
+ assert_raises(Enumerable::SoleItemExpectedError, match: "infinite range '1..' cannot represent a sole item") do
+ (1..).sole
+ end
end
end
設計判断
Range#sole の実装は self.begin.nil? || self.end.nil? という単一の guard で無限範囲を検知し、Enumerable::SoleItemExpectedError を raise しています。テストが beginless のみだったことは、guard の網羅性を十分に検証できないリスクを残していました。今回のテスト追加は実装を変更せず guard の全パスを確認するだけの最小限の改修であり、後方互換性に影響を与えない設計判断と評価できます。
まとめ
無限範囲の両端ケースに対するテストが揃ったことで、Range#sole の例外挙動が完全に保証されます。テストだけの変更であるため、プロダクションコードへの影響はなく、既存利用者へのリスクはゼロです。今後の変更が guard ロジックを破壊しないか CI が自動的に検出できるようになりました。