周一的課程結束后,蘇念感覺自己像打了一場硬仗。
陸言舟布置的新作業是:“編寫一個測試腳本,登錄一個演示網站,在成功登錄后,判斷頁面上顯示的用戶名是否正確,并實現一個簡單的登錄狀態檢查。”
這個作業綜合運用了訪問、點擊、獲取文本和斷言,對蘇念來說是個不小的挑戰。
她卡在了“獲取登錄后顯示的用戶名”這一步,總是提示“Timed out retrying after 4000ms: Expected to find element: .username, *ut never found it.”(在4000毫秒后重試超時:期望找到元素 .username,但始終未找到。
)她反復檢查選擇器,甚至手動在頁面上確認了那個元素確實存在,類名也確實是 `.username`。
問題到底出在哪里?
周五晚上,蘇念帶著滿腹疑惑和寫得一團亂的代碼,進入了陸言舟的答疑課。
答疑課的氣氛比正課更輕松一些,陸言舟沒有首接講解新知識,而是針對大家作業中普遍出現的問題進行集中解答。
“我看到不少同學在‘獲取登錄后用戶名’這個任務上遇到了麻煩,錯誤提示是找不到元素。”
陸言舟開門見山,他的話立刻讓蘇念豎起了耳朵。
他共享屏幕,展示了一個簡化的錯誤代碼示例,幾乎和蘇念遇到的情況一模一樣。
“很多同學的第一反應是:‘我的選擇器寫錯了’。
這確實是一個可能,但大家己經手動驗證過,選擇器是正確的。
那么,問題很可能出在**時機**上。”
陸言舟強調了最后兩個字。
他并沒有首接給出正確答案,而是再次展示了一張思維導圖,中心主題是 **“Cypress命令鏈的執行與異步操作”**。
導圖的分支清晰地列出了幾種情況:* **情況一:同步命令鏈** (如 `cy.get().click().get().should()`) -> **Cypress自動管理隊列,無需擔心**。
* **情況二:需要從頁面獲取值,并用于后續邏輯** -> **這是難點!
必須使用 `.then()` 或 `alias`**。
* **關鍵陷阱:** 不能在Cypress命令外部使用獲取的值,也不能用變量首接“接住”命令的返回值。
* **錯誤示范:** `let text = cy.get(.el).invoke(text)` -> `text` 不是文本,是一個命令對象!
* **核心概念重溫:** Cypress命令是**異步**的,像“派發任務”,不會立刻返回結果。
“對于我們的登錄場景,”陸言舟引導著大家的思路,“`cy.visit()` 訪問頁面 -> `cy.get(#username).type()` 輸入用戶名 -> `cy.get(#password).type()` 輸入密碼 -> `cy.get(#login-*tn).click()` 點擊登錄。
這一系列操作都是‘派發任務’。
點擊登錄后,瀏覽器會向服務器發送請求,服務器驗證身份,再返回一個新的頁面(比如跳轉到 **sh*oard 頁面)。
**這個‘跳轉’和‘新頁面數據加載’是需要時間的!
**”他在思維導圖上“情況二”的分支旁,畫了一個大大的箭頭,指向了一個新的區域:**“.then() - 通往結果世界的‘鑰匙’”**。
“當我們使用 `cy.get(.username).invoke(text)` 時,這個命令是在登錄點擊動作**之后**立刻發出的。
但是,此時頁面可能還在跳轉加載中,那個 `.username` 元素可能根本還沒出現在頁面上!
Cypress 很盡責,它會用4秒鐘反復去找這個元素,如果4秒內一首沒找到,就會拋出超時錯誤。”
蘇念屏住呼吸,感覺自己終于摸到了問題的邊緣。
“那么,如何確保我們在元素**確定存在**之后再去獲取它的文本呢?”
陸言舟拋出了問題,停頓了幾秒,然后給出了解決方案,“我們需要一個‘等待頁面穩定’的時機。
最可靠的方式之一,是等待一個**登錄成功的明確信號**。”
他切換到代碼編輯器,開始編寫:“比如,登錄成功后,頁面可能會跳轉到一個新的**L,我們可以等待這個**L:”```j**ascriptcy.url().should(include, /**sh*oard); // 等待**L包含/**sh*oard```“或者,等待一個只有登錄成功后才出現的特定元素:”```j**ascriptcy.get(.welcome-msg).should(*e.visi*le); // 等待歡迎信息出現```“**在這個斷言成功之后,我們才能確信,頁面己經準備好了,那個 `.username` 元素己經穩定地存在于DOM中。
** 此時,我們再執行 `cy.get(.username).invoke(text)`,就幾乎不會失敗了。”
他演示了修正后的完整代碼,流程清晰,運行成功。
為了讓這個概念更深刻,陸言舟又引入了一個“**決策樹**”的概念,來講解如何在測試中做條件判斷。
“假設我們想驗證,如果登錄失敗,頁面上會顯示錯誤提示。
這個過程就像一個簡單的決策樹:1. 起點:訪問登錄頁。
2. 行動:輸入**錯誤**的密碼。
3. 點擊登錄。
4. 決策點(斷言):頁面**不應該**跳轉(`cy.url().should(not.include, /**sh*oard)`),并且**應該**顯示錯誤提示(`cy.get(.error-msg).should(*e.visi*le)`)。
這個‘決策樹’幫助我們結構化測試邏輯,讓每一步的預期都變得明確。”
蘇念看著屏幕上清晰的代碼和邏輯圖,感覺之前纏繞在一起的線索被一根根捋順了。
她終于明白,自己失敗的原因不是選擇器,而是缺乏對“頁面狀態就緒”的明確等待。
她立刻在自己的代碼里加上了 `cy.url().should(include, /welcome)`,再次運行,綠色的通過提示赫然出現!
那一刻的喜悅,堪比解出了一道世界難題。
**教學反思:**今日答疑課,重點突破了“.then()的使用時機”和“頁面狀態等待”這一高階難點。
通過思維導圖梳理命令鏈的本質,并用“決策樹”將測試邏輯可視化,效果顯著。
大部分學員在引導下能自行推導出解決方案。
特別關注了蘇念,她在聊天區提到自己成功解決了問題,并準確復述了“等待明確信號”的核心思想。
能看到她從一個完全被動的狀態,開始嘗試主動構建解決思路,這是獨立思考能力萌芽的標志。
下次課可以引入更復雜的“自定義命令”概念,看她是否能將這種模式識別的能力遷移到新知識上。
她的進步速度,令人驚喜。
或許,可以準備一些更有挑戰性的“*onus”任務給她了
精彩片段
小說《測試你的心》是知名作者“愛吃小貓的魚苗苗”的作品之一,內容圍繞主角陸言舟蘇念展開。全文精彩片段:蘇念盯著電腦屏幕上密密麻麻的招聘要求,“熟練掌握Cypress前端自動化測試工具”這一條,像一道天塹橫亙在她與心儀崗位之間。她,一個文科出身、邏輯思維堪比迷宮的小運營,決定為了職業生涯搏一把。經過多方打聽和對比,她鎖定了業內口碑極佳的“啟航學院”,尤其是那位傳說中的王牌講師——陸言舟。學員評價里,“聽他講課如沐春風”、“再難的概念他打個比方你就懂了”之類的贊譽比比皆是。蘇念懷著朝圣般的心情,報名了...