【AI測試 Skill進階】03 | 健壯元素定位:UI變更時測試不崩潰的Skill
整理版優先睇
用呢個 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 嘅設計根基。
// ❌ 唔好咁寫
await page.locator('.phone-input').fill('13800138000');
// ✅ 要咁寫
await page.getByPlaceholder('請輸入手機號').fill('13800138000');
標準 2:多備選,一顆紅心兩手準備。大部分人只寫一種定位方式,揾唔到就死。好嘅定位器應該有備選:用 .or() 組合多個定位器,呢個唔掂換嗰個。
const loginBtn = page
.getByRole('button', { name: '登錄' })
.or(page.getByRole('button', { name: '立即登錄' }))
.or(page.locator('[type="submit"]'));
標準 3:操作前先檢查,唔好預期元素一定存在。加上 count > 0、isVisible、isEnabled 三重檢查,代碼就由「碰運氣」升級為「穩紮穩打」。
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 定位」、「寫一個唔崩嘅定位器」。
// 手機號輸入框
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 分鐘,仲要大機率下次再崩。
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 個崩潰源
每寫一個定位器,你可能踩中了這些坑:
//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 自動推薦最優定位器:
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 自動組合多個備選,不是"要麼全對要麼全錯":
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 步即可:
PART 05
實戰操作:從 30 分鐘到 5 分鐘
場景: sogoodtool.com 登錄頁,UI 迭代後測試全崩
傳統手寫定位器(約 30 分鐘):
.login-btn → 測試,找不到,原來開發改了類名 | |
//div[@class="form"]/button → 測試,還是不行,開發調整了結構 | |
playwright-robust-locators(約 5 分鐘):
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 做的不是讓你寫更復雜的代碼,而是讓你寫更簡單但穩健的代碼。更重要的是,它內嵌了一套"好的定位器應該怎麼寫"的方法論——用用戶能看見的、多備選、操作前檢查——哪怕不用這個工具,這 3 個標準也值得在日常中堅持。
寫一個用例省 20 分鐘,一天省 2 小時,一個月省 40 小時。告訴 AI 頁面是什麼,看它 5 秒給你生成什麼樣的定位器。
想要獲取完整的 Skill 安裝包,加入知識星球領取~

