【AI測試 Skill進階】03 | 健壯元素定位:UI變更時測試不崩潰的Skill

作者:AI應用實踐進階
日期:2026年4月29日 下午10:00
來源:WeChat 原文

整理版優先睇

速讀 5 個重點 高亮

用呢個 AI Skill,UI 點變測試都唔崩 — playwright-robust-locators 實戰指南

整理版摘要

呢篇文章係一位測試工程師分享佢點樣用 AI Skill 解決元素定位器脆弱嘅問題。佢話測試工程師成世約 40% 時間都用喺維護定位器度:開發改個類名、重構頁面結構、UI 一迭代,啲用例就全軍覆沒。最慘係改定位器只係力氣活,唔係技術活,浪費時間又冇成長。

作者喺呢篇文章介紹咗一個叫「playwright-robust-locators」嘅 Skill,專治定位器脆弱。佢先拆解咗元素定位嘅 4 個崩潰源:硬編碼 XPath、唔檢查就操作、單一定位器冇退路。然後提出咗好定位器嘅 3 個標準:用用戶睇得到嘅文字/角色、多備選、操作前檢查。成個 Skill 嘅設計就係圍繞呢 3 個標準。

最後結論係:用 AI 自動生成健壯定位器,可以將單個用例嘅定位器維護時間由 15-30 分鐘降到 3-5 分鐘,而且 UI 點變都仲頂得住。就算唔用呢個工具,嗰 3 個標準都值得日日堅持。

  • 元素定位器維護佔測試工程師約 40% 時間,係最大嘅時間浪費源。
  • 好定位器嘅 3 個標準:用用戶可見文字(getByRole/getByPlaceholder)、多備選(.or() 組合)、操作前檢查(count/isVisible/isEnabled)。
  • 傳統手寫定位器平均 15-30 分鐘,用 AI Skill 只需 3-5 分鐘,仲要更穩陣。
  • 核心啟發:定位器唔好依賴 CSS 類名,而家 Playwright 嘅語義化定位先係王道。
  • 可行動點:即刻叫 AI 用 playwright-robust-locators 幫你生成定位器,或者手動跟足 3 個標準寫。
整理重點

元素定位嘅 4 個崩潰源

測試工程師成世約 40% 時間都用喺維護定位器,呢個唔係段子。開發改個類名,你原來嘅 .login-btn 就揾唔到;開發重構頁面結構,原嚟嘅 XPath 徹底失效;UI 一迭代,你啲測試用例全紅一片。更頭痛嘅係,改定位器唔係技術活,係力氣活 — 睇頁面、試定位、重寫,無限 loop。

  • 硬編碼 XPath:用下標 //div[2]/button[3],頁面結構一變就全錯。
  • 唔檢查就操作:預設元素一定存在,實際可能冇渲染。
  • 單一定位器冇退路:只寫一種方式,揾唔到就報錯。
  • 一個測試用例由 UI 迭代到修復通過,平均耗時 15-30 分鐘。每日跑 20 個用例,光改定位器就耗 2-3 個鐘。
整理重點

好定位器嘅 3 個標準

介紹工具之前,先回答一個根本問題:點樣嘅定位器,UI 點變都唔崩?作者提出三個標準,係成個 Skill 嘅設計根基。

程式內容 javascript
// ❌ 唔好咁寫
await page.locator('.phone-input').fill('13800138000');
// ✅ 要咁寫
await page.getByPlaceholder('請輸入手機號').fill('13800138000');

標準 2:多備選,一顆紅心兩手準備。大部分人只寫一種定位方式,揾唔到就死。好嘅定位器應該有備選:用 .or() 組合多個定位器,呢個唔掂換嗰個。

程式內容 javascript
const loginBtn = page
 .getByRole('button', { name: '登錄' })
 .or(page.getByRole('button', { name: '立即登錄' }))
 .or(page.locator('[type="submit"]'));

標準 3:操作前先檢查,唔好預期元素一定存在。加上 count > 0、isVisible、isEnabled 三重檢查,代碼就由「碰運氣」升級為「穩紮穩打」。

程式內容 javascript
const count = await loginBtn.count();
if (count > 0) {
 const isVisible = await loginBtn.first().isVisible();
 const isEnabled = await loginBtn.first().isEnabled();
 if (isVisible && isEnabled) {
 await loginBtn.first().click();
 }
}
整理重點

playwright-robust-locators 點樣解決問題

呢個 AI Skill 嘅核心能力係自動生成健壯定位策略:自動推薦定位方式(getByRole > getByPlaceholder > getByText > CSS/XPath)、自動組合備選(用 .or())、自動檢查狀態(count/isVisible/isEnabled)、自動畀出常見模式(輸入框、按鈕、連結等)。觸發關鍵詞包括「幫我寫一個定位器」、「用 robust 定位」、「寫一個唔崩嘅定位器」。

程式內容 javascript
// 手機號輸入框
const phoneInput = page
 .getByPlaceholder('請輸入手機號')
 .or(page.locator('[placeholder="請輸入手機號"]'))
 .or(page.locator('input[type="tel"]'));

// 登錄按鈕
const loginBtn = page
 .getByRole('button', { name: '登錄' })
 .or(page.getByRole('button', { name: '立即登錄' }))
 .or(page.locator('button[type="submit"]'));

解決 2:自動組合備選,唔係「要麼全對要麼全錯」。例如「輸入框」會自動組合 placeholder + attribute + id,「連結」會組合 getByRole + text。解決 3:自動加檢查邏輯,唔會上來就操作。就算元素被隱藏、被禁用、唔存在,都唔會報錯。

整理重點

實戰對比:30 分鐘 vs 5 分鐘

場景係 sogoodtool.com 登錄頁 UI 迭代後測試全崩。傳統手寫定位器約 30 分鐘:寫 .login-btn → 原來開發改咗類名,揾 10 分鐘;睇頁面寫 XPath → 又唔得,開發調整咗結構,再 10 分鐘;反覆試終於得,用咗 5 分鐘。總共 25 分鐘,仲要大機率下次再崩。

程式內容 javascript
test('登錄流程 - 健壯定位器版本', async ({ page }) => {
 const phoneInput = page
 .getByPlaceholder('請輸入手機號')
 .or(page.locator('[placeholder="請輸入手機號"]'))
 .or(page.locator('input[type="tel"]'));
 const codeInput = page
 .getByPlaceholder('請輸入驗證碼')
 .or(page.locator('[placeholder="請輸入驗證碼"]'));
 const loginBtn = page
 .getByRole('button', { name: '登錄' })
 .or(page.getByRole('button', { name: '立即登錄' }))
 .or(page.locator('button[type="submit"]'));
 // 操作前檢查...
});

對比一下:傳統手寫只有一種定位、唔檢查狀態、UI 迭代後大機率全紅;AI skill 生成嘅代碼有備選、有檢查、UI 變咗大機率仲行到。寫一個用例省 20 分鐘,一日省 2 個鐘,一個月省 40 個鐘。作者最後提醒:就算唔用呢個工具,用用戶可見嘅、多備選、操作前檢查呢 3 個標準都值得日日堅持。

"一個測試工程師,職業生涯中大約有40%的時間花在定位器維護上。"

這不是段子。開發改了個類名,你原來的 .login-btn 找不到元素了;開發重構了頁面結構,原來的 XPath 徹底失效;UI 一迭代,你的測試用例全紅一片。更頭疼的是,改定位器不是什麼技術活,就是個力氣活——一遍一遍地看頁面,一遍一遍地試,一遍一遍地重寫。

本文介紹 playwright-robust-locators,一個專治定位器脆弱的 skill,讓你寫出的測試代碼,UI 怎麼變,測試都不崩潰。


PART 01

元素定位的 4 個崩潰源

每寫一個定位器,你可能踩中了這些坑:

崩潰源
典型表現
根因
硬編碼 XPath
頁面結構一調,定位器徹底失效
用下標 //div[2]/button[3],結構變了全錯
不檢查就操作
元素被隱藏了還點,報錯
以為元素一定存在,實際可能沒渲染
單一定位器
找不到就報錯,沒有退路
只寫了一種方式,沒考慮備選

一個測試用例從 UI 迭代到修復通過,平均耗時 15-30 分鐘。每天跑 20 個用例,光改定位器就耗掉 2-3 小時。

這些時間本可以花在更有價值的測試設計上。


PART 02

好定位器的 3 個標準

在介紹工具之前,先回答一個更根本的問題:什麼樣的定位器,UI 怎麼變都不崩?


標準 1:用用戶能看見的,不用 CSS 類名

❌ .login-btn

❌ .submit-btn

❌ .css-123abc

✅ page.getByRole('button', { name: '登錄' })

✅ page.getByPlaceholder('請輸入手機號')

✅ page.getByText('立即登錄')

公式: 用用戶能看見的文字/標籤/角色,不用開發隨便改的類名。

sogoodtool.com 例子:

// ❌ 不要這樣寫
await page.locator('.phone-input').fill('13800138000');

// ✅ 要這樣寫
await page.getByPlaceholder('請輸入手機號').fill('13800138000');

標準 2:多備選,一顆紅心兩手準備

大部分人只寫一種定位方式,找不到就報錯。好的定位器應該有備選:

❌ 只有一種,找不到就掛

await page.locator('.login-btn').click();

✅ 多備選,這個不行換那個

const loginBtn = page
  .getByRole('button', { name: '登錄' })
  .or(page.getByRole('button', { name: '立即登錄' }))
  .or(page.locator('[type="submit"]');

sogoodtool.com 例子:

// ✅ 登錄按鈕的多個備選
const loginBtn = page
  .getByRole('button', { name: '登錄' })
  .or(page.getByRole('button', { name: '立即登錄' }))
  .or(page.locator('button:has-text("登錄")'));

標準 3:操作前先檢查,不要指望元素一定存在

99% 的定位器沒有檢查,直接操作。加上這幾條,你的代碼從"碰運氣"升級為"穩紮穩打":

const count = await loginBtn.count();
if (count > 0) {
  const isVisible = await loginBtn.first().isVisible();
  const isEnabled = await loginBtn.first().isEnabled();
  if (isVisible && isEnabled) {
    await loginBtn.first().click();
  }
}

playwright-robust-locators 的設計完全圍繞這 3 個標準。


PART 03

playwright-robust-locators 如何解決

AI 定位器助手 能夠根據頁面描述自動生成健壯的定位策略。

核心能力:

  • 自動推薦定位方式:getByRole > getByPlaceholder > getByText > CSS/XPath
  • 自動組合備選:用 .or() 自動組合多個定位器
  • 自動檢查狀態:count > 0、isVisible、isEnabled
  • 自動給出常見模式:輸入框、按鈕、連結等常用模式

觸發關鍵詞: "幫我寫一個定位器"、"用 robust 定位"、"寫一個不崩的定位器"、"健壯元素定位"


解決 1:自動避開 CSS 類名,優先用語義化

支持 4 種輸入方式,AI 自動推薦最優定位器:

輸入方式
示例
元素文字
"按鈕文字是'登錄'" → getByText
功能說明
"這是個輸入框" → getByPlaceholder
截圖描述
"按鈕在右上角" → 組合多種方式

sogoodtool.com 完整例子:

// 手機號輸入框
const phoneInput = page
  .getByPlaceholder('請輸入手機號')
  .or(page.locator('[placeholder="請輸入手機號"]'))
  .or(page.locator('input[type="tel"]'));

// 登錄按鈕
const loginBtn = page
  .getByRole('button', { name: '登錄' })
  .or(page.getByRole('button', { name: '立即登錄' }))
  .or(page.locator('button[type="submit"]'));

// 驗證碼輸入框
const codeInput = page
  .getByPlaceholder('請輸入驗證碼')
  .or(page.locator('[placeholder="請輸入驗證碼"]'));

解決 2:自動組合備選,一顆紅心兩手準備

AI 自動組合多個備選,不是"要麼全對要麼全錯":

場景
自動組合
輸入框
'請輸入用戶名' + '[placeholder="username"]' + '#username'
連結
'忘記密碼' + 'getByRole("link")'

sogoodtool.com 例子:

// sogoodtool.com 首頁的"立即體驗"按鈕
const startBtn = page
  .getByRole('link', { name: '立即體驗' })
  .or(page.getByRole('button', { name: '立即體驗' }))
  .or(page.locator('a:has-text("立即體驗")'));

不再是"只寫一種",而是"這個不行換那個",穩妥。


解決 3:操作前檢查,先確認再動手

自動加檢查邏輯,不是上來就操作:

const loginBtn = ...;
const count = await loginBtn.count();
if (count > 0) {
  const isVisible = await loginBtn.first().isVisible();
  const isEnabled = await loginBtn.first().isEnabled();
  if (isVisible && isEnabled) {
    await loginBtn.first().click();
  }
}

哪怕元素被隱藏、被禁用、不存在,都不會報錯。


PART 04

怎麼用


對話式寫定位器(最簡單)

直接對 AI 說,帶上關鍵詞即可:

幫我寫一個登錄按鈕的定位器,要 robust 的

描述頁面寫:

這是 sogoodtool.com 的登錄頁:
- 有個輸入框,placeholder 是"請輸入手機號"
- 有個按鈕,文字是"登錄"
- 按鈕在輸入框下面
幫我用 robust 定位器寫個登錄流程

指定用 Skill:

用 playwright-robust-locators skill 幫我寫

在 Trae CN 中使用

Skill 的本質是結構化 Prompt + 參考標準,3 步即可:

步驟
操作
2
正常對話:"幫我寫登錄頁的定位器"
3
看 AI 生成的代碼,複製到測試用例裏

PART 05

實戰操作:從 30 分鐘到 5 分鐘

場景: sogoodtool.com 登錄頁,UI 迭代後測試全崩


傳統手寫定位器(約 30 分鐘):

步驟
耗時
寫 .login-btn → 測試,找不到,原來開發改了類名
10 分鐘
看頁面,看 XPath → 寫 //div[@class="form"]/button → 測試,還是不行,開發調整了結構
10 分鐘
反覆試,終於找到一個能用的
5 分鐘

playwright-robust-locators(約 5 分鐘):

步驟
耗時
AI 自動生成完整代碼(含備選、檢查)
1 分鐘
人工審核一下,複製到用例
3 分鐘
運行測試,通過
30 秒

sogoodtool.com 完整示例代碼

import { test, expect } from '@playwright/test';

test.describe('sogoodtool.com 登錄測試', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('https://sogoodtool.com/login');
  });

  test('登錄流程 - 健壯定位器版本', async ({ page }) => {
    // 手機號輸入框 - 多個備選
    const phoneInput = page
      .getByPlaceholder('請輸入手機號')
      .or(page.locator('[placeholder="請輸入手機號"]'))
      .or(page.locator('input[type="tel"]'));

    // 驗證碼輸入框 - 多個備選
    const codeInput = page
      .getByPlaceholder('請輸入驗證碼')
      .or(page.locator('[placeholder="請輸入驗證碼"]'));

    // 登錄按鈕 - 多個備選
    const loginBtn = page
      .getByRole('button', { name: '登錄' })
      .or(page.getByRole('button', { name: '立即登錄' }))
      .or(page.locator('button[type="submit"]'));

    // 操作前檢查:手機號輸入框
    const phoneCount = await phoneInput.count();
    if (phoneCount > 0) {
      const isVisible = await phoneInput.first().isVisible();
      const isEnabled = await phoneInput.first().isEnabled();
      if (isVisible && isEnabled) {
        await phoneInput.first().fill('13800138000');
      }
    }

    // 操作前檢查:驗證碼輸入框
    const codeCount = await codeInput.count();
    if (codeCount > 0) {
      const isVisible = await codeInput.first().isVisible();
      const isEnabled = await codeInput.first().isEnabled();
      if (isVisible && isEnabled) {
        await codeInput.first().fill('123456');
      }
    }

    // 操作前檢查:登錄按鈕
    const loginCount = await loginBtn.count();
    if (loginCount > 0) {
      const isVisible = await loginBtn.first().isVisible();
      const isEnabled = await loginBtn.first().isEnabled();
      if (isVisible && isEnabled) {
        await loginBtn.first().click();
      }
    }
  });
});

playwright-robust-locators 生成的代碼包含 4 類核心信息:

1. 定位方式優先級: getByRole > getByPlaceholder > getByText > CSS/XPath。讓你知道哪種最穩。

2. 備選組合: 自動用 .or() 組合多個定位器,一個不行換另一個。

3. 狀態檢查: count > 0、isVisible、isEnabled。確保操作前確認。

4. 常見模式: 輸入框、按鈕、連結等常用模式,直接套用。


對比:playwright-robust-locators skill 生成 vs 傳統手寫

維度
傳統手寫
playwright-robust-locators
備選策略
只寫一種,全有全無
自動組合多個備選
狀態檢查
通常不檢查,直接操作
自動 count/isVisible/isEnabled
UI 迭代後
大概率全紅
大概率還能跑
單個用例耗時
15-30 分鐘
3-5 分鐘

寫在最後

元素定位是自動化測試的基礎,但"基礎"不等於"脆弱"。

playwright-robust-locators 做的不是讓你寫更復雜的代碼,而是讓你寫更簡單但穩健的代碼。更重要的是,它內嵌了一套"好的定位器應該怎麼寫"的方法論——用用戶能看見的、多備選、操作前檢查——哪怕不用這個工具,這 3 個標準也值得在日常中堅持。

寫一個用例省 20 分鐘,一天省 2 小時,一個月省 40 小時。告訴 AI 頁面是什麼,看它 5 秒給你生成什麼樣的定位器。

想要獲取完整的 Skill 安裝包,加入知識星球領取~


圖片
交流微信,請備註來源和來意:
圖片
【AI 測試 Skill 入門篇】01 | 環境搭建:Node.js + Playwright + Trae CN 全指南
【AI 測試 Skill 入門篇】02 | 第一個自動化測試