2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ブラウザゲームのセーブを再読み込み後に検証する

2
Posted at

ブラウザゲームの手動セーブを確認するとき、保存成功の表示だけでは、再読み込み後に元のデータを復元できたか分かりません。保存スロットのJSONと、ロード後の画面の値を一緒に比べる検査を作りました。

今回はTeristorialの2026年10月14日の公開ファイルをローカルに固定し、App Crash Lab 0.4.1で確認しています。通常の保存とロードはPASS。復元前に同じスロットを意図的に上書きする比較用の操作ではFAILになりました。ゲームの不具合を発見したという結果ではありません。

保存スロットと復元後の表示を比べる

使った流れは、Arden Reachを開始し、ゲームを一時停止してSlot 1へ保存、ページを再読み込み、Slot 1を明示的にロードする、というものです。

保存されたJSONには92地区分のレコードがあり、この開始状態で所有する地区は12です。検査ではスロットのJSON全体に加えて、領土名、所有地区数、一時停止の表示、画面の金と穀物を観測します。ロード完了の表示も待ってから比較します。

保存データだけが残っていても、ロード処理や表示への反映が壊れている可能性があります。逆に、見えている2つの数字が同じでも、他の保存項目が変わっている可能性があります。それぞれを比較対象にしました。

実測結果

2026年10月14日、macOS arm64、Node 22.16.0、Playwright 1.64.0での運営側の実行結果です。

操作 結果 主な比較値
通常の保存、再読み込み、明示ロード PASS、差分0 金240→240、穀物180→180、保存スロットのJSONが一致
復元前にSlot 1を意図的に上書きしてからロード FAIL、差分359 金242→251、保存時刻や地区の値も変化
通常の検査から生成したPlaywright単独テスト 1 passed App Crash Labをimportせず同じ流れを実行

通常と上書きの行は別の実行です。リアルタイムのゲームなので、保存した瞬間の金や経過時間は実行ごとに変わります。毎回240を期待するのではなく、その実行で保存した値と、ロード後の値を比べます。

画像はこの実測レポートです。

通常の保存と明示ロードでPASSになった実測レポート

復元前の意図的上書きでFAILになり金242から251の差分を検出した実測レポート

上書きの比較は、テストが変化を検出できるかを確かめる負例です。正常な操作でデータが消えた、という意味にはしません。

手元で再現する

実行用ZIPとSHA256を公開しています。ZIPのSHA256は次の値です。

1e3fb0b089f76a5f6e8ac3a1293073787c85875dca90f2959e6d63417ebbb30a

Python 3、Node 22以上、npmを用意します。ZIPを展開し、teristorialディレクトリで1つ目のターミナルから実行してください。

python3 prepare-local.py --out site
python3 -m http.server 54263 --bind 127.0.0.1 --directory site

helperは公式サイトの17ファイルを取得し、SOURCE.jsonのファイル長とSHA256を照合します。既存の出力ディレクトリは上書きしません。公式ファイルが更新されて照合に失敗した場合は、保存データの判定まで進んでいません。新しい版のfixtureを用意してから検査します。

サーバーを動かしたまま、2つ目のターミナルを同じteristorialディレクトリで開きます。

npx --yes --package=@playwright/test@1.64.0 playwright install chromium
npx --yes --package=https://github.com/aichance/business-ai-recipes/releases/download/app-crash-lab-v0.4.1/aichance-app-crash-lab-0.4.1.tgz app-crash-lab run contract.json --out .crash-lab/teristorial-first

出力された絶対パスのindex.htmlを開くと、保存時と検査後の値、差分、ブラウザtraceを確認できます。通常の検査の終了コードは0です。再実行時は別の出力ディレクトリを使ってください。

次は意図的な上書きの比較です。

npx --yes --package=https://github.com/aichance/business-ai-recipes/releases/download/app-crash-lab-v0.4.1/aichance-app-crash-lab-0.4.1.tgz app-crash-lab run overwrite-control.json --out .crash-lab/teristorial-overwrite

こちらは終了コード1と比較段階のFAILが期待結果です。終了コード2なら設定、起動、インフラなどの問題で、保存の判定ができなかった状態です。

自分のアプリに移すときの観測項目

今回の設定の一部です。savedSlotは保存されたJSON全体、renderedGoldは画面の数字を観測しています。

{
  "checks": ["reload"],
  "observe": {
    "savedSlot": {
      "source": "localStorage",
      "key": "teristorial:save:slot1",
      "parse": "json"
    },
    "renderedGold": {
      "source": "text",
      "target": { "css": "#goldValue" }
    }
  }
}

これは設定の抜粋で、単独の実行用設定ではありません。実際のcontract.jsonには起動後の操作、保存成功の待機、ロード完了の待機などが入っています。自分のアプリでは、キーやselectorに加えて「いつ保存が完了したか」と「いつ復元が完了したか」を決めてください。

ソースを手元に持つ方は、自己アプリ用の導入プロンプトを普段のコーディングエージェントへ渡す方法もあります。実際の保存処理を調べ、アプリに合わせた設定を作り、ローカルで実行して結果を確認する依頼文です。CLI自体はLLMやAPIキーを使いません。

生成したテストを次の更新で使う

通常の検査で表示されたレポートディレクトリへ移動し、アプリのサーバーを動かしたまま実行します。

npm install --prefix . --no-save --package-lock=false --ignore-scripts @playwright/test@1.64.0
npx playwright test --config playwright.config.mjs

生成されたspecはPlaywrightをimportします。App Crash Lab本体をimportせず、選んだ保存操作の再現テストとして再実行できます。終わったらアプリサーバーをCtrl+Cで停止してください。

今回の範囲は、手動のSlot 1、保存JSON、選んだ復元後の表示です。自動セーブ、破損データの拒否、ブラウザ強制終了、クラウド保存、マルチプレイは検査していません。Windowsでのこのpackの実行も未検証です。

App Crash Labは私がAIで開発、検証、運用するMITのOSSです。ゲーム本体は作者の作品で、このZIPには再配布していません。検査設定とhelper、実測のRESULTS.jsonを配布しています。GitHubリポジトリを、次の保存機能の変更時にも使ってもらえるよう改善しています。自分のアプリでの結果や、設定で止まった箇所は短い報告フォームから教えてください。実データや資格情報は不要です。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?