使用 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),否則你會得到兩個 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 |
| 交易 | 確認、拒絕、餘額不足、Gas 飆升、已取代或加速的交易、來自合約的回滾 |
| 代幣授權 | 授權精確數量 vs 無限、授權後花費、未授權即花費 |
| 待處理狀態 | 在等待時重新載入、關閉分頁後返回、連續兩筆交易 |
| 顯示 | 交易後的餘額(UI vs 鏈)、小數點與四捨五入、非常大的數額與極小的粉塵金額 |
在錢包中拒絕與確認同樣重要。許多 dApp 在拒絕後會永遠卡在「等待 確認」狀態。
撰寫測試
模式(完整檔案在 examples/transfer.spec.ts):
- 使用
viem從鏈上讀取起始狀態(getBalance、readContract)。 - 使用 Playwright 定位器驅動 dApp UI,並使用
MetaMask輔助工具驅動錢包 (connectToDapp、confirmSignature、confirmTransaction、rejectTransaction、switchNetwork)。 - 從 UI、事件或網路回應取得交易雜湊,然後
waitForTransactionReceipt。 - 斷言收據狀態 以及 新的鏈上狀態。然後斷言 UI 與之相符。
將與錢包無關的邏輯(金額驗證、格式化、錯誤文案)放在使用 Synpress 的以太坊錢包 mock 或 使用 mock provider 的純 Playwright 測試中,以加快執行速度。僅在擴充功能本身重要的流程中使用 真實的 MetaMask。
要尋找的典型錯誤
- UI 顯示成功,但收據狀態為
reverted,或收據根本不存在。 - UI 中的餘額是快取的,交易後未重新整理。
- 金額精度:18 位小數的代幣顯示時出現浮點四捨五入;最大按鈕留下粉塵或超出 餘額 1 wei。
- 切換鏈後,dApp 繼續呼叫舊鏈的合約地址。
- 被拒絕的簽名使按鈕保持禁用狀態,直到重新載入。
- 在第一筆交易待處理時,相同的操作可以被提交兩次。
- 治理:UI 中計算了投票,但鏈上的提案狀態未改變(錯誤的提案 ID、在截止區塊後投票)。
回報 Web3 錯誤時需提供
網路和鏈 ID、合約地址、錢包地址(僅限測試錢包)、交易雜湊和
區塊號碼、收據狀態、UI 顯示的內容 vs 鏈顯示的內容、MetaMask 版本。
區塊瀏覽器連結(或帶有 cast run <txhash> 的 Anvil 追蹤)是最佳的證據。