Flaky test_update_thread_pool_min_max の安定化
test_update_thread_pool_min_max が Expected: 3, Actual: 2 で失敗するフレークが解消されました。テスト内部のスリープ時間を 0.001 秒から 0.1 秒に延長し、リクエストがスレッドプールに十分にキューイングされるようにしただけで、期待通りにスレッドが生成されます。
背景
このテストは スレッドプールの最小・最大スレッド数 が正しく適用されるかを検証する重要なものです。元の実装では sleep 0.001(1ミリ秒)の遅延が設定されており、TCP 接続やスレッドスケジューリングのオーバーヘッドと同程度の時間でした。その結果、既存スレッドが次のリクエストを処理し終える前に新しいリクエストが到着し、race condition が発生してスレッドが再利用され、期待した 3 スレッドが生成されませんでした。
テストが不安定になると CI の信頼性が低下し、実装変更の検証に余計なノイズが入ります。そこで、タイミング依存を解消し、テストが決定的に成功するように調整が必要となりました。
技術的な変更
テストコードの遅延量を拡大するだけのシンプルな修正です。test/test_puma_server.rb の該当メソッド内で sleep 0.001 を sleep 0.1 に置き換えました。
@@ -2189,9 +2189,10 @@ def test_stats_ok_before_run
end
def test_update_thread_pool_min_max
- # add a small delay so requests back up
+ # delay enough that 5 requests back up faster than threads finish them,
+ # so the pool spawns up to max rather than reusing the existing thread
@app = ->(env) do
- sleep 0.001
+ sleep 0.1
[200, {}, [env['rack.url_scheme']]]
end
変更前は 1 ミリ秒の遅延で、リクエストがスレッド完了とほぼ同時に到着し、プールが新規スレッドを生成しないケースが頻発していました。変更後は 100 ミリ秒の遅延が確実にリクエストをキューに貯め、プールが最大数までスレッドを生成できるようになり、assert_equal 3, @pool.spawned が常に成功します。
この修正はテストロジックのみに影響し、実際の Puma 本体の挙動やパフォーマンスには一切変更を加えていません。
設計判断
テストのタイミング感度を減らす という方針が採用されました。スレッドプールのロジックそのものは正しいにも関わらず、テスト環境の微小遅延が不確実性を招いていたため、最小限の侵襲で確実性を確保する選択が行われました。
代替案としてはテストコードをリトライロジックで包む、あるいはモックでスレッド生成を強制するなどがありますが、追加のテスト補助コードはテストの可読性を下げ、将来的なメンテナンスコストを増大させる恐れがあります。単にスリープ時間を調整するだけで、テストの意図は変わらず、コードベースへの副作用も最小限です。
この判断により、テストの信頼性が向上し、CI の安定運用が継続できるだけでなく、将来的に同様のレースコンディションを伴うテストへの指針としても有用です。
まとめ
test_update_thread_pool_min_max のフレークは、スリープ遅延を 0.001 秒から 0.1 秒に増やすだけで解消されました。タイミング依存のテストに対しては、最小限の環境調整で決定的な結果を得ることが最も効果的であるという設計判断が示されています。これにより Puma のスレッドプール機能の検証が安定し、継続的インテグレーションの品質が保たれます。