Coerce stream name to String in test adapter accessors

rails/rails

テストアダプターがブロードキャストを取得する際に、チャネル名を文字列に統一しないため、シンボルで指定したストリームが正しく検出されず、assert_no_broadcasts が実際のレグレッションを見逃す問題を解消しました。

背景

テスト実行時に シンボル でストリーム名を指定することは慣例的に行われていましたが、ActionCable::Server::Broadcasting では書き込み時に String(broadcasting) で文字列化して保存していました。SubscriptionAdapter::Test#broadcasts#clear_messages が生の引数をキーに使っていたため、保存側と取得側で型が揃わず、assert_broadcasts(:foo, …) が 0 件と判定されたり、assert_no_broadcasts(:foo) が実際にはメッセージが送信されていても 通過 してしまうケースが発生していました。この不整合はテストの信頼性を損ね、潜在的な回帰を隠す危険性がありました。

技術的な変更

actioncable/lib/action_cable/subscription_adapter/test.rbbroadcastsclear_messages メソッドで、チャネル名を String(channel) に強制変換してからハッシュのキーとして使用するよう修正しました。これにより、シンボル・文字列問わず同一キーでメッセージが格納・参照されます。

@@
- def broadcasts(channel)
-   channels_data[channel] ||= []
+ def broadcasts(channel)
+   channels_data[String(channel)] ||= []
 end
@@
- def clear_messages(channel)
-   channels_data[channel] = []
+ def clear_messages(channel)
+   channels_data[String(channel)] = []
 end

さらに、actioncable/test/test_helper_test.rbtest_assert_broadcasts_with_symbol_stream テストを追加し、シンボルストリームでのブロードキャスト検証が正しく成功することを自動確認できるようにしました。

@@
+ def test_assert_broadcasts_with_symbol_stream
+   assert_nothing_raised do
+     assert_broadcasts(:test, 1) do
+       ActionCable.server.broadcast :test, "message"
+     end
+   end
+ end

設計判断

今回の修正は 読み取り側書き込み側 と同一の文字列化ロジックに合わせるというシンプルな選択です。新たなパラメータや API を導入せず、既存のハッシュキー生成ロジックに String(channel) 変換を追加しただけなので、既存のコードベースへの影響は最小限に抑えられます。また、String(channel) は既に broadcast メソッドで使用されているため、型一貫性が保証され、テストアダプターの動作が全体のデータフローと整合します。

まとめ

テストアダプターがシンボルストリーム名を正しく扱えるように変更したことで、assert_no_broadcasts が実際のレグレッションを隠す問題が解消されました。書き込みと読み取りのキー生成を統一したシンプルな設計は、既存コードへのリスクを抑えつつテスト信頼性を向上させます。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
ca8ab902

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文、背景、技術的な変更、設計判断(任意)、まとめの5要素がすべて揃っており、総論→各論→結論の流れが明確です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

コードブロックはファイル名付きシンタックスハイライト(```ruby:filepath)が正しく使用され、PRへのリンクも #57698 形式で正しくリンク化されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

Rails の内部テストアダプターに関する記述で、専門的なエンジニア向けの内容になっており、余計な初心者向け解説はありません。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションは総論・各論・結論の段落構成で、トピックセンテンスが先頭にあり、1段落1トピック、段落長も6文未満で空行で区切られています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事に掲載されたコードブロックは提供された Diff と完全に一致しており、ファイル名・変更箇所・追加テストも正確です。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「broadcasts」「clear_messages」「String(channel)」「assert_no_broadcasts」などの用語は PR と一致し、誤用はありません。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

技術的な影響や問題点の説明が PR のサマリーと整合しており、因果関係も正しく記述されています。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事の全ての主張は PR の記載内容・Diff に裏付けられており、外部知識や推測は含まれていません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR 番号 #57698、テストで使用されている期待件数 1 など、数値は正確です。

タイトル・説明との一致 ⚠ WARNING

記事タイトル・説明とPR内容の一致

記事タイトルが PR タイトルの "the" を省略しており、完全一致ではありませんが意味上は問題ありません。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

バージョンサポート状況やリリース予定など、PR に記載されていない外部情報は記載されていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現の記述はなく、PR と矛盾する表現もありません。