昨天你亮了第一個綠燈。今天不寫新測試,改做三件事:故意弄壞它、請 AI 解釋它、學會它失敗時怎麼判讀。這一天花下去,後面幾篇都會輕鬆很多。順便跟「失敗訊息」正式見個面,之後好幾天它會常來,今天把它變成看得懂的東西。
第一件事:故意弄壞它,而且弄壞三次
請 Claude Code 把驗證的字改成一個不存在的詞,例如「Playwrong」,再跑一次,看它變紅。改回來,再看它變綠。
這個動作在確認一件事:這個測試真的有在驗證,不會永遠都過。一紅一綠之間,你對「測試在做什麼」的體感,比讀十頁文件都深。
別只弄壞一次。三種弄法各做一遍,你會看到三種長相不同的紅燈:
• 弄壞預期(驗證字改成 Playwrong):訊息會出現 Expected 和 Received 的對照,期望含 Playwrong、實際是 Playwright。這種叫斷言失敗:網頁打開了、東西也讀到了,只是跟預期不符。日後看到它,先想是產品變了,還是預期寫錯了。
• 弄壞網址(改成不存在的 playwright.devvv):訊息會提到連線錯誤,net::ERR 之類的字樣。這種紅燈根本沒走到驗證,在動作階段就掛了。日後看到它,先查環境和網址。
• 弄壞等待(請它把逾時上限暫時改成 1 毫秒):你會看到 Timeout 逾時錯誤,意思是等了規定的時間,條件還沒滿足。成因最多樣,也最需要判讀功力。
三次做完,把三種訊息並排比一比。會分辨紅燈的長相,除錯就有了方向,你已經贏過很多看到紅色就重跑的人。你不是在靠運氣, 你是真的會去看看哪邊有出錯。
第三種弄法需要多說兩句, 因為「逾時上限」藏在哪不明顯, 你可能不知道要怎麼弄。它就在測試程式裡、驗證那一行的選項上。你可以對 Claude Code 說:
你可以這樣對 Claude Code 說:
把 first-test.spec.js 裡驗證標題那行的逾時上限暫時改成 1 毫秒,跑給我看結果。
它改完,那行大概長這樣: (LLM 最大的特色, 相同提示輸入, 會產生不同結果, 所以你的生成結果一定不會和我的內容都相同)
await expect(page).toHaveTitle(/Playwright/, { timeout: 1 });
直覺上,網頁不可能 1 毫秒內載入好,應該會失敗 (紅燈會出現)。但你跑下去,很可能看到的是:綠燈,照樣通過。
先講結論:timeout 的意思是「如果東西還沒好,我最多願意等多久」。東西已經好了,這條規則根本沒機會用上。
用一個情境想。你去麵包店驗收蛋糕:
• 店員的習慣是:等蛋糕完全出爐、擺好,才開門請你進來。所以你一進門,蛋糕一定是好的。這個店員就是 goto——它預設等網頁載入完成,才放行到下一步。
• 你進門先看一眼:蛋糕好了,蓋章通過,走人。這是斷言的習慣——先立刻檢查一次,對了就直接過。
• timeout: 1 是你的耐心:「如果進門時蛋糕還沒好,我只願意等 1 毫秒」。但蛋糕早就好了,你的耐心多短都無所謂。
這就是綠燈的原因:斷言到場時,標題早就在了,看一眼就過,timeout 完全沒上場。
想真的看到 Timeout,就得「提早進門」——趁蛋糕還在烤就衝進去,而且只肯等 1 毫秒。程式上,就是叫 goto 不要等載入完成。請 Claude Code 幫忙:
你可以這樣對 Claude Code 說:
我想親眼看 Timeout 錯誤。請把 first-test.spec.js 改成:goto 不等頁面載入完成(waitUntil 用 commit),標題驗證維持 { timeout: 1 },跑給我看失敗結果。
改完關鍵兩行長這樣:
await page.goto('https://playwright.dev',
{ waitUntil: 'commit' });
await expect(page).toHaveTitle(/Playwright/, { timeout: 1 });
waitUntil: 'commit' 就是「門一開就進去,不等出爐」。這時標題還沒生出來,你又只肯等 1 毫秒,必然失敗。錯誤訊息大概長這樣:
1) first-test.spec.js:4:1 › homepage title
Error: Timed out 1ms waiting for
expect(page).toHaveTitle(expected)
Expected pattern: /Playwright/
Received string: ""
Call log:
- expect.toHaveTitle with timeout 1ms
- unexpected value ""
逐段讀。第一行 Timed out 1ms 直接點名失敗原因:時間到了。Expected 還是那個期望的字樣,但注意 Received 是空字串——不是標題錯,是標題根本還沒生出來,就被迫交卷了。Call log 記錄它用 1 毫秒的上限試過、拿到的值不對。
拿它跟第一種弄壞(改成 Playwrong)的紅燈並排比:兩張長得很像,都有 Expected 和 Received,但線索完全不同。改壞預期的那張,Received 是完整的真實標題——東西在,只是跟預期不符,該去查預期或產品。逾時的這張,開頭寫著 Timed out、Received 空空的——東西還沒到,該去查等待和環境。之後在真實案子裡看到紅燈,先看這兩個記號,方向就對了一半。
看完請它把兩處改動都拿掉,恢復原狀。回頭看這一輪,你其實多賺了一課:預測、實驗、被結果糾正——這個循環本身,就是搞懂一套工具最快的方法。
第二件事:請它逐行解釋,然後追問
直接說:
你可以這樣對 Claude Code 說:
請逐行用白話解釋 first-test.spec.js 在做什麼,假設我完全不會寫程式。
讀完解釋別停在「喔,懂了」,用追問把理解釘牢。三個好用的追問:
• 「如果我要改成驗證頁面上有個 Get started 按鈕,哪一行要變?怎麼變?」看動作和斷言怎麼對應。
• 「哪一行拿掉之後,測試會永遠通過?」答案是 expect 那行。這個問題直指測試的靈魂,第 7 篇會展開。
• 「這五行裡,哪些是每個測試都長一樣的骨架,哪些是這個測試獨有的內容?」把格式和內容分開,之後讀任何測試都快。
追問的訣竅:請它「改一個小地方給你看」,不要請它「再解釋一次」。看差異比看說明有效。
第三件事:失敗時的標準動作
昨天如果紅燈不請自來,你已經做過一次「整段複製丟給 AI」。今天把它整理成完整的循環:

圖 1:遇到錯誤訊息的標準處理循環
有兩個關鍵。第一,整段複製,不要只貼最後一行。Playwright 的錯誤訊息其實有結構,拿你剛才弄壞預期時看到的那份當例子,大致長這樣:
2) 1) first-test.spec.js:3:1 › homepage title
Error: expect(page).toHaveTitle(expected)
Expected pattern: /Playwrong/
Received string: "Fast and reliable end-to-end testing
for modern web apps | Playwright"
Call log:
- expect.toHaveTitle with timeout 5000ms
- 9 × unexpected value ...
由上往下讀:第一段說哪個測試、檔案第幾行失敗;中間是重點,Expected 是測試期望的、Received 是實際拿到的,兩個一對照,問題通常就現形了;最下面的 Call log 記錄它嘗試了什麼、等了多久,那個「9 ×」是說它重試了九次都不符合。整包都是診斷材料,只貼最後一行,等於只給醫生看一張腳趾照片。
第二,補上脈絡:「我剛執行了某某指令,出現以下錯誤,在這之前我改過某某地方」。給 AI 的資訊品質,決定它診斷的品質。給開發者報 bug,道理一樣。
除了終端機,還有一份網頁版報告
失敗訊息除了在終端機看,還有一個更舒服的地方。輸入:
npx playwright show-report
瀏覽器會打開一份 HTML 報告:每個測試一列,綠勾紅叉一目瞭然,點進失敗的測試能看到同樣的錯誤內容,排版好讀很多,失敗當下的截圖也常常附在裡面。之後測試多了,這份報告會是你每天看的東西,今天先知道它的入口。
如果你在終端機中下上面 “npx playwright show-report”不成功的話, 可以試著在 claude code 中打這個指令, Claude Code 應該會給你一些說明為什麼不會成功, 或者你也可以試著把出現的訊息, 丟給 Claude Code, 詢問他要如何調整才能成功。
為什麼第一個測試要那麼小

圖 2:第一個測試的野心要刻意壓小
你可能會想,測個標題有什麼用。以測試價值來說,確實沒什麼用。但以學習來說,它讓你在最少的干擾下走完整條路:描述、產碼、執行、回饋、除錯,今天每一步都停下來摸清楚了。
學習路徑有個原則:一次只引入一個新變數。今天的場景小到不可能是場景的問題,出任何狀況都能安心歸因到環境或工具,除錯範圍很小。等這條路走順,場景再逐步加大。表單是第二週的事,完整購物流程更後面。
今天的練習
• 基本題:在官方示範站 demo.playwright.dev/todomvc 再產一個測試:新增一筆待辦「買牛奶」,驗證清單出現這一筆。然後照本篇的三種弄法,把它弄壞三次,認識三種紅燈。
• 進階題:請 Claude Code 在同一個測試裡加第二個驗證:新增後,左下角的剩餘數量應顯示 1 item left。
• 挑戰題:先自己預測,如果把網址和驗證字同時弄壞,紅燈會報哪一種錯?想好再動手驗證。答案:網址那關先掛,輪不到斷言,因為測試是一行一行照順序執行的。這個體感很重要。