Skip to content

2. テストの実態

「どれくらいのテストを行ったのか」への回答。このセッションのテストは アサートスイートではなく、実ブラウザ内で本物のフレーム更新関数を大量に駆動して観測する「観測駆動型」 だった。累計 10 万フレーム以上 のシミュレーションが実行されている。

テスト量の全体像

テスト規模目的
スパイラル走行プレイテスト数万フレーム移動・吸収・成長・ストリーミング・カメラの一気通貫検証
空白地帯での成長停滞走行20,000+ フレームワールドのバンド構造の確認(結果的に仕様通りと判明)
シェルチャンク上限の修正検証70,000+ フレーム描画コールが 12 で頭打ちになるか、fps 維持(62–70fps を確認)
勝利後の連続吸収ストレス60,000+ フレーム最大半径到達後のチャンク肥大が上限 400 で止まるか
リスタート連打ストレス5 サイクル連続GPU リソース解放修正後のエラー有無
本番デプロイ検証実ブラウザ + curlコンソールエラー 0、デバッグフックの本番排除確認

最初の壁: 「ゲームが動かない」の切り分け

テスト開始直後、ブラウザ自動化(claude-in-chrome)でキー入力を送ってもボールが一切動かない現象に遭遇した。ここでの切り分けがこのセッションのデバッグ性能を象徴している。

症状: ボールは動かず、サイズも変わらず、コンソールエラーもない。しかしページ読込直後にワールドのオブジェクトは配置されている。

切り分け: ページコンテキストから document.hidden / document.visibilityState を直接確認 → 両方とも hidden / true。自動化タブは OS のフォアグラウンドタブではないため、Chrome が requestAnimationFrame を完全にサスペンドしていた。つまりゲームのバグではなく、バックグラウンドタブに対するブラウザの正常動作だった。読込直後だけワールドが populate されていたのは、スロットリングが効き切る前の最初の数 rAF ティックでストリーミングの初期ランプアップが完了していたため──症状の細部まで矛盾なく説明されている。

なぜこれが重要か

「動かない → コードをいじって直そうとする」ではなく、「動かない → 環境要因を疑って観測で確定させる」という順序を踏んでいる。存在しないバグの修正(=回帰の混入)を構造的に避けた例。

テストハーネスの自作: window.__manualStep

rAF が止まる環境でもテストできるよう、毎フレーム処理を step(dt, input) 関数に抽出し、本物の requestAnimationFrame ループと dev 専用フック window.__manualStep(dtMs, input) の両方から呼ぶ構造に変更した。

  • テストは 実プレイヤーのフレームと完全に同一のコードパス を通る(テスト専用の別実装ではない)
  • import.meta.env.DEV でガードし、本番バンドルには含めない
  • デプロイ後、本番サイトで window.__manualStep / __debug / __setRadius がすべて undefined であることまで検証済み(「dev ガードを書いた」で終わらせず「本番から消えた」を確認している)

プレイテストのシナリオ設計

単純な直進ではなく、原点から徐々に旋回半径を広げるスパイラル走行を採用した。理由: ワールドはサイズバンドごとにオブジェクトの生息域が異なるため、直進では小物クラスタを素通りしてしまう。実際、初期の直進テストでは 20,000 フレーム以上成長が停滞したが、これは「ワールドが一様スープではなく、大きいバンドは本当に遠くにしか居ない」という設計の確認として活用された。

このシナリオで検証されたもの:

  • 移動・旋回・転がり回転: デバッグフック経由で位置・速度を追跡し正常
  • 吸収 + 体積保存成長: 半径 0.15m → 0.48m → 4.2m → 11.5m → 30.9m →(テレポートテストで)300m まで滑らかに成長し、三乗成長モデルの理論的な減速カーブと一致
  • ワールドストリーミング: アクティブオブジェクトは 0(疎な遠隔地)〜 700+(密集地)で変動しつつ、ワールド描画コールは終始 29 で一定(プロトタイプごとに 1)
  • カメラ: 直径 0.3m 〜 600m まで距離・FOV・near/far が連続的に追従し、z-fighting・クリッピングなし
  • 勝利条件: 最大半径でバナーと最終 HUD が正しく表示

観測可能性への投資

修正の検証を可能にするため、開発用統計オーバーレイに maxChunkParts メトリクスを追加してから検証を行っている。「直したはず」ではなく「上限 400 に張り付いて動かないことを 60,000 フレーム観測した」と言える状態を先に作った。この「観測手段を先に整備してから修正を検証する」動きは、このセッションのデバッグスタイルの核と言える。

このテストで見つかった不具合

プレイテスト段階で 2 件の実バグを発見・修正した(詳細は不具合カタログ)。devlog 自身が次のように総括している:

どちらも、最初の「動いてそう」なスクリーンショットで止めず、その先まで押し込む長時間・敵対的なプレイテストだからこそ捕まえられた。

一方で、このセッションには ヘッドレスのアサートスイート(回帰テスト資産)が存在しない ことも事実で、これは Fable 5 版(約 3,000 アサート)との明確な違いになる。比較ページで詳しく扱う。

本サイトは Claude (Fable 5) がセッションログ・devlog・Qiita 記事を突き合わせて作成した分析ドキュメントです。