4Hえんぴつ|React+TypeScriptでWeb RPGを作る
第8章「Web公開・互換性・永続化」
第43回:localhostだけで終わらせない――production URLへ同じE2Eをかける
1. 今回のテーマ
前回は、
Browser
↓
Netlify
↓
SPA fallback
↓
index.html
↓
React
↓
React Router
という流れで、
直URLや再読み込みでもSPAを起動できるようにする方法を扱いました。
ここで、もう一つ確認したいことがあります。
それは、
localhostで通ったE2Eが、実際のproduction URLでも同じように通るか
です。
開発環境で動いていたとしても、公開環境では、
hosting設定
HTTPS
SPA fallback
build成果物
public URL
IndexedDB
などが絡みます。
そこで今回は、
同じE2Eシナリオをproduction URLでも再利用する
考え方を整理します。
2. localhostでPASSしてもproductionで同じとは限らない
開発中は、
例えば、
http://localhost:5173
のようなURLで確認します。
ここでは、
Viteの開発サーバーが動いています。
一方、正式公開後は、
https://adventure-web-mvp-phase-g-g06-v1-6-0.netlify.app/
で動きます。
同じReactアプリでも、
実行環境は違います。
3. productionでは別の要素が加わる
productionでは、
localhostにはなかった要素が入ります。
例えば、
Netlify
HTTPS
production build
redirect設定
SPA fallback
実際の公開URL
です。
そのため、
localhostで動いた
=
productionでも動く
とは言い切れません。
4. 同じ仕様を別の環境で確認する
ただし、
productionだから、
別のゲームとしてテストするわけではありません。
確認したい仕様は同じです。
例えば、
タイトルが開く
/characterを直URLで開ける
/saves?mode=manageを再読み込みできる
未知URLはfail-closedする
セーブから再開できる
などです。
つまり、
同じ仕様を、実行環境だけ変えて確認する
という考え方です。
5. baseURLを切り替える
Playwrightでは、
baseURLを使って、
テストコード側のURL指定を共通化できます。
以下は考え方を説明するため、実装を簡略化しています。
use: {
baseURL: process.env.E2E_BASE_URL,
}
テスト側は、
以下は考え方を説明するため、実装を簡略化しています。
await page.goto("/character");
のように書けます。
実行時に、
E2E_BASE_URL=http://localhost:4173
ならlocal、
E2E_BASE_URL=https://production.example.com
ならproduction、
という形で切り替えられます。
6. テストコードをlocal専用にしない
例えば、
以下は考え方を説明するため、実装を簡略化しています。
await page.goto(
"http://localhost:4173/character"
);
と書いてしまうと、
productionでは使いにくくなります。
そのため、
テストシナリオ
↓
環境非依存
接続先URL
↓
設定で切り替える
形にします。
7. 同じE2Eを使う意味
localとproductionで、
別々のテストコードを書くこともできます。
しかし、
内容がほぼ同じなら、
両者がずれていく可能性があります。
例えば、
localではH07まで確認
productionではH05までしか確認していない
という状態です。
同じE2Eを再利用すれば、
同じ仕様を同じ観点で確認しやすくなります。
8. production用に別シナリオを増やすのではない
重要なのは、
productionだから
テストを別物にする
ことではありません。
むしろ、
同じrelease candidate
↓
local hosting
↓
同じ確認
同じrelease candidate
↓
production hosting
↓
同じ確認
とします。
確認対象が同じだからこそ、
環境差を見つけやすくなります。
9. productionではroot起動も確認する
正式公開版では、
production rootが正常に返り、
v1.6.0が起動することを確認しています。
つまり、
production URL
↓
HTTP 200
↓
アプリ起動
までが最初の受入です。
E2Eの前提として、
そもそも公開物が正しく配信されている必要があります。
10. 直URLはproductionで特に重要になる
第42回で扱った、
/character
/saves?mode=manage
の直URLは、
productionでこそ確認する価値があります。
なぜなら、
SPA fallbackやredirect設定は、
hosting側の責務だからです。
localhostでPASSしても、
productionのredirect設定が間違っていれば、
直URLは失敗します。
11. 未知URLもproductionで確認する
例えば、
/unknown-route
へ直接アクセスした場合です。
期待するのは、
404で停止
ではなく、
SPA fallbackでReactを起動し、
React Router側で、
unknown
↓
安全な画面
へ戻すことです。
これもproduction hostingの設定とアプリ側の両方が関係します。
12. 期限切れ結果URLもproductionで確認する
また、
/result
のように、
そのURLだけでは成立しない画面もあります。
必要なGameStateがない状態でアクセスした場合、
空画面
例外
ではなく、
fail-closedする必要があります。
正式公開版では、
期限切れ結果URLのfail-closedもproduction受入項目になっています。
13. console warning/errorもproductionで0件を見る
localでconsoleが静かでも、
productionだけで出る問題があります。
例えば、
build後の挙動差
hosting由来の問題
外部リソース
などです。
そのため、
第39回で扱った、
console warning/error
pageerror
もproductionで再確認します。
正式公開版では、production受入でも0件を確認しています。
14. セーブ→タイトル→つづきからもproductionで確認する
productionでは、
単に画面が表示されるだけでなく、
IndexedDBによる永続化が本当に機能するかも重要です。
正式公開版では、
セーブ
↓
タイトルへ戻る
↓
つづきから
↓
ロード
という復帰導線をproductionで確認しています。
つまり、
Router
+
IndexedDB
+
GameState復元
+
production hosting
までつないで確認しています。
15. localとproductionで同じ7項目を確認する
正式受入では、
hosting確認を、
local production-hosting
7 / 7 PASS
production hosting
7 / 7 PASS
としています。
重要なのは、
localで別の7項目、
productionで別の7項目、
ではなく、
同じ観点を両方で通したこと
です。
16. 「buildできた」と「公開先で動く」は別
production buildが成功していても、
それだけでは公開成功とは言えません。
例えば、
npm run build
↓
PASS
でも、
hosting設定が間違っていれば、
直URLは404になります。
そのため、
Build
↓
Artifact
↓
Hosting
↓
Production URL
↓
E2E
まで進めます。
17. build artifactと公開物の境界を見る
正式公開では、
production buildだけでなく、
hosting artifact verificationもPASSしています。
つまり、
正しいコードを書いた
だけではなく、
正しい成果物ができた
その成果物が公開環境で動いた
までを確認します。
18. production E2Eは「デプロイ確認」でもある
production URLへE2Eをかけると、
アプリの機能だけでなく、
正しい版が公開されているか
も確認できます。
例えば、
画面に、
Web MVP Phase G v1.6.0
が表示されることを確認すれば、
想定している版が起動していることの一つの証拠になります。
19. production URLはテスト対象そのものになる
開発中は、
URLは単なる接続先に見えます。
しかし公開後は、
このURLで
この版が
この挙動をする
こと自体が製品仕様になります。
そのため、
production URLを、
正式なテスト対象
として扱います。
20. 本番テストでは状態を変えすぎない
productionへE2Eをかけるときは、
本番データを壊さないように注意が必要です。
今回のWeb RPGは、
ブラウザローカルのIndexedDBを使っているため、
サーバー側の共有データを変更する構成ではありません。
それでも、
どの操作を行うか
は明確にしておきます。
21. fresh sessionで確認する意味
既存のブラウザ状態を使うと、
以前のIndexedDB
以前のcache
既存session
が影響する可能性があります。
そのため、
公開確認では、
fresh sessionでのsmokeも意味があります。
正式版のrollback確認でも、
fresh session smokeをPASSしています。
22. production E2Eはlocalhostの代わりではない
ここで、
productionで確認するなら
local確認はいらない
とはなりません。
localでは、
変更直後に速く確認できます。
productionでは、
実際のhosting環境まで含めて確認できます。
つまり、
local
↓
早く原因を見つける
production
↓
公開環境で成立することを確認する
という役割分担です。
23. 問題が出たら環境差を切り分ける
例えば、
local
PASS
production
FAIL
なら、
アプリロジックそのものより、
redirect
hosting
HTTPS
artifact
環境設定
などを疑いやすくなります。
逆に、
local
FAIL
production
FAIL
なら、
よりアプリ側の問題である可能性が高まります。
24. 同じE2Eだから差分が見える
もしlocalとproductionで、
まったく別のテストを書いていたら、
テスト内容の違い
なのか、
環境の違い
なのか分かりにくくなります。
同じシナリオを使うことで、
比較条件をそろえる
ことができます。
25. productionだけの失敗も品質情報になる
production E2Eで失敗した場合、
それは単なるデプロイ作業の失敗ではありません。
公開環境では成立しない
という製品品質上の情報です。
そのため、
正式公開判定では、
production hosting PASSを条件にします。
26. 公開URLでIndexedDB保持まで確認する
正式版では、
公開URL上で、
保存
上書き
ロード
再読み込み
を行い、
IndexedDBの保持も確認しています。
これは、
productionで画面が開いた
より一段深い確認です。
27. 「同じ候補」を確認することが重要
localでテストしたコードと、
productionへ出したコードが違えば、
比較の意味が弱くなります。
そのため、
正式候補
↓
build
↓
local hosting確認
↓
productionへ公開
↓
production hosting確認
という流れで、
同じ候補を追います。
28. release candidateを途中で変えない
例えば、
local確認後に、
ちょっとだけ修正
してからproductionへ出すと、
localで確認したものと、
productionで確認したものが別になります。
すると、
どの状態でPASSしたのか
が曖昧になります。
そのため、正式公開判定では、
candidateの凍結が重要になります。
29. これは次のrollback設計にもつながる
同じcandidateを固定して確認する考え方は、
次回扱う、
rollback anchor
にもつながります。
exact candidate
↓
production確認
↓
rollback可能性確認
です。
つまりproduction E2Eは、
単なる動作確認ではなく、
release managementの一部になっていきます。
30. 今回のポイント
今回のポイントは3つです。
- localhostで通ったE2Eを、baseURLだけ切り替えてproduction URLでも再利用する
- 直URL・再読み込み・未知URL・期限切れURL・console/pageerror・セーブ復帰を、production hostingでも同じ観点で確認する
- 同じrelease candidateをlocalとproductionで確認し、環境差とアプリ不具合を切り分けやすくする
整理すると、
Same Candidate
↓
Local Hosting
↓
E2E 7 / 7
Same Candidate
↓
Production Hosting
↓
E2E 7 / 7
です。
今回の結論は、
公開前のE2Eは、localhostで終わりではなく、実際にユーザーがアクセスするproduction URLまで通して初めて完了する
です。
31. 次回
次回は、
初回リリースでも戻れるようにする――rollback anchorの設計【第44回】
です。
通常、
rollbackというと、
以前の正常なproduction deploy
↓
そこへ戻す
ことを想像します。
しかし、今回の初回正式リリースでは、
過去の成功production deployが存在しませんでした。
そこで、
exact frozen candidate
↓
INITIAL_RELEASE_ANCHOR
を作り、
controlled switchで一度切り替え、
元の正式deployへ戻せることまで確認しました。
次回は、
「初回リリースなのに、どこへ戻るのか」
という問題をどう解決したかを扱います。
この記事を最後まで読んでいただき、ありがとうございます。
「いいね」を押していただけるとうれしいです。これからの記事づくりの励みになります。
もし気に入っていただけましたら、フォローもよろしくお願いします。
前の記事
第42回 React RouterのSPAをNetlifyで直URL・再読み込み対応する
次の記事
第44回 初回リリースでも戻れるようにする――rollback anchorの設計
連載トップ
第0回 React+TypeScriptで異世界RPGを作る――連載の目的と開発ロードマップ
note関連記事
開発環境で動いたWebゲームを、本番環境へ届ける #24
noteでは、開発環境で動いていたWeb RPGをproductionへ出し、直URL・再読み込み・IndexedDB保持まで確認した背景を制作側の視点から書いています。