iT邦幫忙

2025 iThome 鐵人賽

DAY 8
1
Software Development

Playwright 玩家攻略:從新手村到魔王關系列 第 8

Day 08:軍火庫升級|精通正規式、條件式與多重斷言的進階兵器

  • 分享至 

  • xImage
  •  

上一篇認識了 Assertion(斷言) 的基本應用,except() 自動等待的設計結合多樣性的 matcher 讓我們可以在多變的網路戰場中應對自如,但是,偶爾也會遇到一些較特殊的情境,原本的 matcher 不足以面對刁鑽的斷言需求,這個時候,就必須在 matcher 上面加入一點變化,讓 matcher 裝備升級,才能夠應付更難纏的怪物。

進階應用

自訂 timeout
上一篇有提到,Playwright 的斷言會自動等待,重試直到超過時間為止,我們不需要額外加 timeout,內建的 timeout 預設為 5 秒,但要是我們已知網頁回應速度較慢,想要延長 timeout,但又不希望影響全域的 timeout,可以怎麼做呢?

await expect(locator).toBeVisble({ timeout: 10000 });

只需要在 matcher 加上參數 { timeout: 毫秒 } 就能自訂專屬於這個斷言的 timeout,作法非常簡單。

結合條件與正規式
有些網頁中的同一個元素,可能因為條件不同,會顯示不同的內容,例如 台灣銀行牌告匯率網頁,我們可以觀察一下這個頁面:
https://ithelp.ithome.com.tw/upload/images/20250917/20168913ZZcpqaiJyY.png

<h1> 的文字敘述,會依照時間而不同,如果是營業時間,文字內容會顯示本行營業時間牌告匯率,如果是非營業時間,文字內容會顯示本行非營業時間牌告匯率,這個狀況之下,斷言就能結合條件式以符合網頁內容的變動,讓測試更加穩定,我們可以有幾種方式撰寫:

  1. 條件式判斷:

    test('Taiwan Bank exchange rate - assert 1', async({ page }) => {
      // 導航到目標頁面
      await page.goto('https://rate.bot.com.tw/xrt?Lang=zh-TW');
    
      // 定義兩個 locator
      const openingHours = page.getByText('本行營業時間牌告匯率');
      const offHours = page.getByText('本行非營業時間牌告匯率');
    
      // 判斷可見性,回傳布林值
      const isOpeningVisible = await openingHours.isVisible();
      const isOffVisible = await offHours.isVisible();
    
      // 判斷其中一個顯示就算通過(.toBeTruthy() 驗證結果必須是 true)
      await expect(isOpeningVisible || isOffVisible).toBeTruthy();
    });
    
  2. 使用正規式:

    test('Taiwan Bank exchange rate - assert 2', async({ page }) => {
      // 導航到目標頁面
      await page.goto('https://rate.bot.com.tw/xrt?Lang=zh-TW');
    
      // 預期文字內容以正規式表達
      await expect(page.getByText(/本行(非)?營業時間牌告匯率/)).toBeVisible();
    });
    
  3. 內建 locator 條件式 APIlocator.or

    test('Taiwan Bank exchange rate - assert 3', async({ page }) => {
        // 導航到目標頁面
        await page.goto('https://rate.bot.com.tw/xrt?Lang=zh-TW');
    
        // 使用 locator.or API,只要其中一個 locator 成立就通過測試
        await expect(
            page.getByText('本行營業時間牌告匯率').or(page.getByText('本行非營業時間牌告匯率')
        )).toBeVisible();
    });
    

📌 Did You Know?
實際執行上面三段測試,會發現只有第一個測試能成功通過,這與 Playwright 的 strict mode 有關,在 strict mode 下,會檢查是否「只匹配到唯一元素」,如果頁面上有相同的內容就會報錯,這是在撰寫腳本時需要特別注意的地方!

多元素斷言
有時候我們可能要對多個元素同時進行相同的驗證,如果有一段網頁內容是這樣:

<div id="checkbox">
    <input type="checkbox">
    <input type="checkbox">
    <input type="checkbox">
</div>

我們想一次驗證這 3 個 checkbox 是否被勾選,那麼我們可以這樣做:

// 選取所有的 checkbox locator
const checkboxs = await page.locator('.checkboxes input[type="checkbox"]');

// 驗證每個 checkbox 都被勾選
await expect(checkboxes).toBeChecked();

如此一來,斷言會自動驗證 locator 對應的每個元素,如果有其中一個元素不符合預期,就會回傳錯誤,測試失敗,如果全數通過,測試則繼續進行,以上就是多元素斷言的運用。

撰寫重點

各位已經懂得如何升級斷言,讓它變得更加靈活。無論是透過自訂 Timeout 來增加等待的耐心,活用條件式與正規式來應對動態內容,還是使用多元素斷言來一次驗證所有目標,這些技巧都將大幅提升測試腳本的穩定性與覆蓋率。

然而,掌握了這些運用技巧,不代表每一次攻擊都能百發百中。要成為一位真正的神射手,還必須將以下四條心法融入其中:

  • 【明確】清楚表達預期結果,每個斷言都只驗證一件事
  • 【正確】針對元素的文字、屬性、狀態,選擇對應的 matcher
  • 【穩定】在畫面準備好後才檢查,並且利用內建的自動等待與自動重試機制
  • 【可維護】斷言應該要容易閱讀理解,便於維護

到這裡,我們已經學會了使用如何使用各式各樣的武器(斷言),但要成為傳說中的神射手,就必須懂得打造專屬於自己的武器。接下來,我們將學習如何透過「自訂 matcher」,為你的斷言附上獨一無二的強力魔法!


上一篇
Day 07:精準打擊|expect() 斷言的瞄準與射擊
下一篇
Day 09:斷言擴展術|打造你的專屬 Playwright Matcher
系列文
Playwright 玩家攻略:從新手村到魔王關11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言