Synpressを使用したWeb3 dAppテスト
Web3で最も重要なルール:UIは真実の情報源ではなく、チェーンこそが真実の情報源です。 dAppは、リバートされた、置き換えられた、またはウォレットから送信されなかったトランザクションに対して「成功」と表示する可能性があります。状態を変更するすべてのテストは、オンチェーンチェックで終了します。
セットアップ
最初にプロジェクトが何を使用しているかを確認してください。以下のメモはSynpress v4(Playwrightベース)向けです。v3はCypressベースで、APIが異なります。
npm i -D @synthetixio/synpress @playwright/test viem
package.jsonで"type": "module"を、tsconfig.jsonで"moduleResolution": "Bundler"を使用してください(examples/tsconfig.json参照)。SynpressはESモジュールを提供します。Synpressが依存している@playwright/testのバージョンをインストールしてください(npm ls @playwright/testで確認)。そうしないと、互換性のない型を持つ2つのPlaywrightコピーが作成されます。
テストを高速、無料、再現可能にするためにローカルチェーンを実行します。FoundryのAnvilが一般的な選択肢です。
anvil --chain-id 31337 --block-time 1 # デフォルトのテストニーモニックから10の資金提供されたアカウント
# または、固定ブロックで実際のネットワークをフォークし、コントラクトの状態が実行ごとに同じになるようにする:
anvil --fork-url $RPC_URL --fork-block-number 21000000
実際の資金を保持したことがあるシードフレーズは絶対に使用しないでください。Anvilのテストニーモニック、または専用の使い捨てウォレットを使用し、環境変数に保存し、決してコミットしないでください。
ウォレットのセットアップとキャッシュ
Synpressは、MetaMaskが既に設定されたブラウザプロファイルを構築し、キャッシュするため、テストは毎回ウォレットを再インポートする必要はありません。examples/wallet-setup/basic.setup.tsを参照してください。
npx synpress # wallet-setupフォルダ内のすべての*.setup.tsからキャッシュを構築
セットアップファイルまたはMetaMaskのバージョンが変更されたら、キャッシュを再構築してください。CIでは、拡張機能にディスプレイが必要です。xvfb-runでテストを実行してください。
カバーすべきフロー
| フロー | 実際のバグを見つけるケース |
|---|---|
| 接続 | 初回接続、接続拒否、切断と再接続、ウォレットロック、間違ったアカウント選択 |
| ネットワーク | 間違ったチェーンのdApp、ユーザーがフロー途中でチェーンを切り替える、ウォレットにないネットワークを追加 |
| 署名(SIWE、許可) | 確認、拒否、アカウントAで署名してから送信前にBに切り替える |
| トランザクション | 確認、拒否、残高不足、ガススパイク、置き換えまたはスピードアップされたtx、コントラクトからのリバート |
| トークン承認 | 正確な承認と無制限の承認、承認してから使用、承認なしで使用 |
| 保留状態 | 保留中にリロード、タブを閉じて戻る、連続した2つのトランザクション |
| 表示 | トランザクション後の残高(UIとチェーン)、小数点と丸め、非常に大きな額とダスト額 |
ウォレットでの拒否は確認と同様に重要です。多くのdAppは拒否後、「確認を待っています」のまま永遠に固まります。
テストの書き方
パターン(完全なファイルはexamples/transfer.spec.tsにあります):
viemを使用してチェーンから開始状態を読み取ります(getBalance、readContract)。- PlaywrightロケーターでdApp UIを操作し、
MetaMaskヘルパーでウォレットを操作します(connectToDapp、confirmSignature、confirmTransaction、rejectTransaction、switchNetwork)。 - UI、イベント、またはネットワーク応答からトランザクションハッシュを取得し、
waitForTransactionReceiptを呼び出します。 - レシートのステータスと新しいオンチェーン状態をアサートします。その後、UIが一致することをアサートします。
ウォレットに依存しないロジック(金額検証、フォーマット、エラーコピー)は、SynpressのEthereumウォレットモックを使用した高速テスト、またはモックプロバイダーを使用した通常のPlaywrightでテストしてください。拡張機能自体が重要なフローのみ、実際のMetaMaskを使用してください。
探すべき一般的なバグ
- UIが成功を示しているが、レシートステータスが
revertedである、またはレシートがまったく存在しない。 - UIの残高がキャッシュされ、トランザクション後に更新されない。
- 金額の精度:18桁のトークンが浮動小数点丸めで表示される;最大ボタンがダストを残すか、残高を1 wei超える。
- チェーン切り替え後、dAppが古いチェーンのコントラクトアドレスを呼び出し続ける。
- 拒否された署名により、リロードまでボタンが無効のままになる。
- 最初のトランザクションが保留中に同じアクションが2回送信できる。
- ガバナンス:UIでは投票がカウントされているが、オンチェーンの提案状態は変更されていない(間違った提案ID、期限ブロック後の投票)。
Web3バグの報告に必要な情報
ネットワークとチェーンID、コントラクトアドレス、ウォレットアドレス(テストウォレットのみ)、トランザクションハッシュとブロック番号、レシートステータス、UIが表示した内容とチェーンが表示した内容、MetaMaskのバージョン。ブロックエクスプローラーのリンク(またはcast run <txhash>を使用したAnvilトレース)が最良の証拠です。