每個測試都需要佈景:登入好的狀態、預先存在的資料、到達某個頁面。佈景搭得亂,測試就互相踩腳、單獨跑不動、失敗留垃圾。這篇談 Playwright 的 fixture 機制,和背後真正的大題目:測試資料誰的。
這篇的程式碼一行都不用自己打。fixture 與測試程式都用 Claude Code 產出——你負責寫規格、跑指令、驗收結果。所有提示詞都可以整段複製,方括號的地方換成你們自己的。

圖 1:先分清楚哪些要你動手,哪些不用
站在測試人員的位置上,fixture 這個題目真正天天會碰的只有兩件半:
一、讀懂並使用別人寫好的 fixture
九成的時間你是 fixture 的使用者,不是作者。要會的只有一件事:在測試的參數裡寫下 fixture 的名字,Playwright 就會在測試開始前幫你把東西準備好、結束後收乾淨。

圖 2:準備、測試、清理的生命週期。清理走反向順序,測試失敗也照跑。
三個性質先記住,第三節會用它們解釋一件更大的事:
● 清理一定執行。測試失敗也照清,失敗的測試不會留一地垃圾害到別人。
● 沒宣告就不會建。十個測試裡只有兩個要訂單,另外八個就不會付出建訂單的時間。beforeEach 做不到這件事,它對整個檔案一視同仁。
● fixture 之間可以互相依賴。A 需要 B,Playwright 會自己排出建立順序,再以反向順序清理。
接手既有專案時,fixture 檔裡大概會看到三種,它們通常是一兩個人建好的,你只是受益者:
● 登入狀態:用一支獨立的 setup 專案先登入一次,把 cookie 與 localStorage 存成檔案,其他測試直接載入。看設定檔裡的 projects 與 storageState。
● Page Object 注入:讓測試直接拿到組好的 page object,不必每個測試自己 new。看 fixtures 資料夾裡名字有 page 或 pom 的檔。
● auto fixture:加了 { auto: true } 的 fixture,每個測試都會自動套用。它是隱形的——你會遇到「測試明明過了,卻報一個沒印象的錯誤」,搜尋 auto: true 就找得到。
二、動手做:用 Claude Code 產出第一個 fixture
目標:把「開啟 TodoMVC 並預先加三筆待辦」包成 fixture,讓測試本體只剩驗證。用官方練習站,不需要任何後端。先建一個空專案:
npm init playwright@latest fixture-lab
cd fixture-lab
claude
步驟 1:讓它產出 fixture 與測試
請幫我建立一個 Playwright fixture 練習。
目標網站:https://demo.playwright.dev/todomvc/
1. 建立 fixtures/todo-fixtures.ts,匯出一個名為 todoPage 的 fixture,
型別是 Page。它要在測試前開啟該網站、依序加入三筆待辦
(買牛奶、寫測試、交報告),並確認畫面上真的有三筆之後才交給測試。
測試結束後清空 localStorage。
2. 建立 tests/todo.spec.ts,寫兩個測試,都用 todoPage 這個 fixture:
- 勾選第一筆之後,未完成數量顯示 2
- 勾選第一筆之後切到 Active 分頁,只看得到兩筆
限制:測試本體不要有任何 goto 或新增待辦的程式碼,那些都應該在
fixture 裡。選擇器請用 getByTestId / getByRole / getByPlaceholder,
不要用 CSS class。
驗收標準:npx playwright test tests/todo.spec.ts 要全綠。
請你自己跑一次確認,失敗的話告訴我原因再修。
最後那兩句是關鍵。Claude Code 可以自己執行指令,把驗收標準寫進去,它會跑到綠為止,而不是丟一份沒驗過的程式碼給你。
步驟 2:你自己驗收
npx playwright test tests/todo.spec.ts --headed
用瀏覽器開著跑一次,你會看到三筆待辦被輸入進去、然後測試才開始動作。接著打開 tests/todo.spec.ts,看兩件事:
☐ 測試本體是不是真的只剩兩三行?如果 goto 還留在測試裡,那 fixture 就白包了——回去補一句「測試本體不要有 goto」再讓它改。
☐ 斷言驗的是業務規則,還是只驗「頁面有載入」?每個 expect 前面都有 await 嗎?漏掉 await 的斷言永遠不會紅。
步驟 3:把 fixture 從隱形變成看得見
測試本體乾淨了,但那三筆待辦到底在哪裡被輸入進去?畫面上一閃而過,不特別看是看不到的。用 UI 模式跑一次:
npx playwright test tests/todo.spec.ts --ui
點開任何一個測試,左邊的步驟清單最上面有一段 Before Hooks。展開它,todoPage 做的每一件事都在裡面:goto、三次 fill、三次 press,一步一步照順序列著,每一步都可以點進去看當下的畫面。測試跑完之後的 After Hooks,就是清空 localStorage 那一段。
這個畫面值得多看兩眼。fixture 平常是隱形的,測試檔上看不出它做了什麼,但它其實一步都沒少做——只是被收進了 Before Hooks 裡。
三、fixture 到底要拿來解決什麼問題
剛才那個 todoPage,說穿了只是幫你少打幾行字。把 goto 跟三筆待辦搬進 fixture,測試變好看了,但就算不搬,測試也不會壞。
這一節要講的是 fixture 唯一非做不可的用途——它是你目前手上唯一能真正解決測試資料互相踩腳的工具。
先看問題長什麼樣
共用固定測試帳號,跑久了資料越積越多。某天「驗證購物車應有 1 件商品」紅了,因為上上週某次失敗的測試留了東西在裡面。
更陰的是測試間的順序依賴:A 建的資料剛好讓 B 通過。哪天 A 沒跑、或平行執行讓順序變了,B 就無故陣亡。這類靈異事件的共同病根:資料不隔離。
要讓資料隔離,每個測試得做到三件事:開始前建立自己專屬的資料、結束後把它刪掉、而且刪除這件事在測試失敗時也要發生。這三件事你當然可以自己在每個測試裡手寫,但寫十個測試就要重複十次,而且只要有一個人忘了寫清理,整個環境又髒回去。
fixture 的三個性質,剛好就是這三件事
所以「測試資料誰的」不是離題,它就是 fixture 這個機制存在的理由。前面那三種常見 fixture 裡,登入狀態跟 Page Object 都是為了少打字,只有資料 fixture 是為了解決一個真的會咬人的問題。
務實一點:不是所有資料都要隔離
圖 3:四種測試資料策略,由左至右隔離度與成本同步上升
理想解是每個測試自建自清:測試開始時用 API(第 18 篇的技能)建立自己專屬的資料,測完刪掉。每個測試於是完全獨立——可以單獨跑、平行跑、任意順序跑。這三個「可以」,是測試套件長大的前提。
圖上中間那兩格是業界的實際落點。真正做到全部自建自清的團隊是少數,多數團隊混用:商品目錄共用種子資料,登入用 worker 帳號池,訂單與購物車自建自清。照資料的性質分別處理,比一刀切實際。
四、把資料 fixture 套到你們自己的系統上
資料 fixture 的形狀到處都一樣:建 → 交給測試 → 刪。真正會卡住的不是這個形狀,而是「你們的系統要怎麼建、怎麼刪」——每家都不同,所以這一節不做模擬,直接用你們自己的 API。
動手之前,先確認三件事
☐ 有沒有一支 API 可以建立你要的那筆資料?(訂單、購物車、會員……)
☐ 有沒有對應的刪除 API?只能建不能刪的話,先看第六節。
☐ 這兩支 API 要不要帶登入權杖?要的話,測試裡原本怎麼登入,fixture 就照那個方式。
三個都有就可以往下。不確定的話,問開發一句「測試環境有沒有可以直接建資料的端點」通常比自己翻文件快。
五、三個診斷指令
下面這些事其實比 fixture 語法更常用。測試無故變紅的時候,先別急著看程式,照這個流程跑一輪,通常五分鐘內就知道病根在哪。

圖 4:三個指令的分診流程
npx playwright test tests/orders.spec.ts --workers=1 # 單執行緒
npx playwright test tests/orders.spec.ts --repeat-each=3 # 連跑三次
npx playwright test tests/orders.spec.ts -g "下單後" # 只跑那一個

要套到自家專案上,把這一整段交給 Claude Code 跑:
請用這三種方式各跑一次 tests/orders.spec.ts,把結果整理成表格給我:
(1) --workers=1 (2) 預設平行 (3) --repeat-each=3
如果有任何一種跑法失敗,對照下面的判斷準則告訴我病根在哪:
- --workers=1 就不紅 → 平行互踩
- 單獨跑會過、整檔跑會紅 → 順序依賴
- 連跑第二次開始紅 → 髒資料累積
- 三種都紅 → 不是資料問題
先不要改程式,我要先看表格。
你要看的是那張表格,不是它的結論。反過來也成立:一組測試如果 單獨跑會過、平行跑會過、連跑三次也會過,它的資料隔離就算及格。
六、你們公司沒有建資料的 API,怎麼辦
這是講到這裡最常收到的問題,也是很多團隊卡住的地方。五個實際可行的做法,由好到差排:
第二個做法可以直接請 Claude Code 幫你評估可行性:
我們的測試環境沒有建立測試資料的 API。請幫我看幾件事:
1. 專案裡有沒有現成的 DB migration 或 seed 腳本可以參考資料結構?
2. 如果要用 SQL 直接建一筆訂單,需要動到哪幾張表、有哪些外鍵限制?
3. 這樣做會繞過哪些商業邏輯?列出風險。
先不要寫程式,我要先評估。
另外兩層保險,跟上面哪一種搭配都成立:
● 資料加前綴:測試建的資料一律用 e2e- 開頭。就算某次 CI 被強制中斷、清理沒跑完,也能靠一支排程工作定期把 e2e- 開頭的資料掃掉。
● 環境定期重置:測試環境每晚從乾淨快照還原。最徹底,但要基礎設施配合,通常不是測試團隊自己能決定的——不過值得提出來。
七、務實的漸進路線
「所有測試立刻改成自建自清」是漂亮但不切實際的口號。有些系統沒有建資料的 API,有些資料本來就該共用。

圖 5:用兩個問題把測試資料分成三類
● 唯讀的共用資料(商品目錄、設定檔):大家共用,沒人改就沒事。
● 測試會寫入的資料(訂單、購物車、個人資料):優先隔離,這是干擾的主要來源。
● 改不動的(沒有 API 可建資料):照第六節那五個做法,由上往下挑一個做得到的。
要盤點自家專案的話,先讓它列清單,你來分類:
掃過 tests/ 底下所有測試,列出「依賴其他測試留下的資料」的地方:
例如用 beforeAll 建資料給多個測試共用、寫死的測試帳號、
在測試外層宣告又被多個測試修改的變數。
每一項告訴我:在哪個檔案第幾行、依賴的是什麼資料、為什麼有風險。
先不要改程式,我要先看全貌。
拿到清單之後,自己照三分法標一遍,從被咬得最痛的那幾個開始改,一次一個。完美的資料隔離是方向,不是入場券。