【AI 測試 Skill 入門篇】02 | 第一個自動化測試

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

整理版優先睇

速讀 5 個重點 高亮

用 playwright-cli Skill 以 sogoodtool.com 做實戰,學寫第一個自動化測試,掌握元素定位優先級同核心 API

整理版摘要

呢篇文章係 AI 測試 Skill 入門系列嘅第二篇,作者係一位專注推廣 Playwright 自動化測試嘅教練,目標係幫已經搭好環境但唔知點開始嘅測試新手快速上手。佢指出常見三大痛點:唔知第一行 code 寫咩、只會 copy-paste 但唔明背後原理、想測實際網站但無從入手。整體結論係:用 playwright-cli Skill 配合結構化嘅學習路徑,由分析頁面、設計測試用例到編寫 code,可以好快寫出第一個可靠嘅自動化測試。

作者以 sogoodtool.com 嘅登錄頁面做實例,逐步拆解點樣用 Playwright 嘅最佳定位方法(getByRole > getByLabel > getByPlaceholder > getByText > getByTestId > CSS/XPath),並設計咗六個測試用例覆蓋正常登錄、錯誤密碼、用戶唔存在、空郵箱、空密碼等場景。每個用例都有明確步驟同斷言,仲提供咗完整嘅 code 範例同執行指令,令讀者可以跟住做。

最後文章總結咗核心知識點:頁面導航、元素定位、元素交互、斷言驗證同等待機制,強調 networkidle 係最推薦嘅等待方式。成個流程由痛點出發,畀出解決方案,再落地到實戰,係一篇高密度、可即用嘅入門教學。

  • playwright-cli Skill 涵蓋瀏覽器啟動、頁面導航、元素定位、交互、斷言、等待同調試,係寫自動化測試嘅基礎工具箱。
  • 元素定位優先級:getByRole 最穩定 -> getByLabel -> getByPlaceholder -> getByText -> getByTestId -> CSS/XPath(唔推薦)。
  • 用語義化定位(role、label)比傳統 CSS/XPath 更抗 UI 變更,係保持測試穩定嘅關鍵。
  • 實戰案例展示咗點樣由分析頁面結構到設計六個測試用例,覆蓋正常流程同邊界情況。
  • 跟住文章嘅 code 範例,任何人都可以喺 sogoodtool.com 上寫出第一個 Playwright 測試並執行。
整理重點

痛點與解決方案:環境搞掂咗,但點樣開始寫測試?

你可能已經裝好 Node.jsPlaywrightTrae CN,但打開編輯器就懵咗:第一行 code 寫咩?點樣打開瀏覽器?點樣定位元素?呢篇文章就係為咗解決呢個問題,用 playwright-cli Skill 帶你寫第一個自動化測試。

好多新手只係識得 copy-paste 網上嘅 code,但唔明 page.goto() 點解要等、getByText() 同 getByRole() 有咩分別、expect() 可以驗證啲咩。呢篇文章會逐一拆解,並以真實網站 sogoodtool.com 做實戰,令你唔再怕寫測試。

整理重點

playwright-cli Skill 核心能力一覽

playwright-cli Skill 包含咗 Playwright 嘅基礎能力,以下係佢嘅核心功能分類:

  • 瀏覽器啟動:支援 ChromiumFirefoxWebKit,可選無頭/有頭模式,設置窗口大小,仲可以多瀏覽器並行執行。
  • 頁面導航:page.goto() 打開 URL、page.reload() 刷新、page.goBack()/goForward() 前進後退,同埋等待頁面加載(waitForLoadState)。
  • 元素定位:推薦 getByRole、getByLabel、getByPlaceholder、getByText,其次 getByTestId,唔推薦 CSSXPath
  • 元素交互:click、fill、selectOption、check/uncheck、press 鍵盤操作。
  • 斷言驗證URL(toHaveURL)、標題(toHaveTitle)、可見性(toBeVisible)、文本(toHaveText)、屬性(toHaveAttribute)、包含(toContainText)。
  • 等待機制:waitFor 元素可見、waitForResponse 網絡請求、waitForNavigation 導航、waitForLoadState(推薦 networkidle)。
  • 調試支援:截圖(screenshot)、錄屏(video)、追蹤(trace)同 Playwright Inspector
整理重點

元素定位優先級:邊種方法最穩陣?

元素定位係自動化測試嘅核心,揀啱方法可以令測試更穩定、更易維護。playwright-cli Skill 提倡嘅優先級由高到低如下:

  1. 1 getByRole(最推薦):語義化定位,例如 getByRole('button', { name: '登錄' }),最穩定。
  2. 2 getByLabel(推薦):適用於表單輸入框,例如 getByLabel('郵箱')。
  3. 3 getByPlaceholder(推薦):適用於有 placeholder 嘅輸入框,例如 getByPlaceholder('請輸入郵箱')。
  4. 4 getByText(推薦):適用於文本內容,例如 getByText('登錄成功')。
  5. 5 getByTestId(儘量用):需要開發配合加 data-testid。
  6. 6 CSS 選擇器(唔推薦):容易受 CSS 類名變化影響。
  7. 7 XPath(唔推薦):最唔穩定,易受 DOM 結構變化影響。
整理重點

實戰案例:測試 sogoodtool.com 嘅登錄功能

作者用 sogoodtool.com 嘅登錄頁面做實例,示範由分析頁面到寫 code 嘅完整流程。首先分析頁面結構:有郵箱輸入框(placeholder「請輸入郵箱」)、密碼輸入框(placeholder「請輸入密碼」)、登錄按鈕(角色 button,名「登錄」)。然後設計咗六個測試用例:

  • TC001:頁面正常加載——驗證標題同輸入框可見。
  • TC002:登錄成功——輸入正確郵箱密碼,驗證跳轉到 dashboard。
  • TC003:密碼錯誤——輸入錯誤密碼,驗證顯示「密碼錯誤」。
  • TC004:用戶唔存在——輸入唔存在嘅郵箱,驗證顯示「用戶唔存在」。
  • TC005:郵箱為空——唔入郵箱,驗證顯示「請輸入郵箱」。
  • TC006:密碼為空——唔入密碼,驗證顯示「請輸入密碼」。

作者提供咗完整嘅 code 範例(tests/login.spec.ts),示範點樣用 test.beforeEach 統一導航,同埋用 getByPlaceholder、getByRole、getByText 定位元素。仲有執行測試嘅指令:

運行測試指令 bash
# 運行所有測試
npx playwright test

# 運行特定測試文件
npx playwright test tests/login.spec.ts

# 在 UI 模式下運行(可以看到瀏覽器操作)
npx playwright test tests/login.spec.ts --ui

# 只運行 Chromium
npx playwright test tests/login.spec.ts --project=chromium

# 生成 HTML 報告
npx playwright test tests/login.spec.ts --reporter=html
npx playwright show-report
整理重點

核心知識點總結:導航、定位、交互、斷言、等待

最後作者歸納咗五大核心知識點,係每個人寫 Playwright 測試都一定要掌握嘅:

  • 頁面導航:page.goto() 打開 URL,搭配 waitForLoadState('networkidle') 確保頁面完全加載。
  • 元素定位:首選 getByRole 同 getByPlaceholder,其次 getByText,避免 CSS/XPath
  • 元素交互:click()、fill()、selectOption()、check()/uncheck()、press()。
  • 斷言驗證:用 expect() 配合 toHaveURL、toBeVisible、toHaveText 等,檢查結果。
  • 等待機制:推薦 waitForLoadState('networkidle'),避免用硬編碼 waitForTimeout。

【AI 測試 Skill 入門篇】02 | 第一個自動化測試:sogoodtool.com 實戰案例

一、難題:環境已經砌好咗,但係唔知點開始寫測試

你係咪有呢啲疑問?

1. 環境砌好咗,但係唔知由邊度入手

你可能已經搞掂咗環境設置:

  • ✅ Node.js 安裝咗
  • ✅ Playwright 安裝咗
  • ✅ Trae CN 都安裝咗

但係一打開編輯器,就懵咗:

  • ❌ 第一行代碼寫啲乜?
  • ❌ 點樣打開瀏覽器?
  • ❌ 點樣定位元素?
  • ❌ 點樣驗證結果?

2. 淨係識得複製貼上,唔知點解要咁寫

你可能喺網上揾到咗一啲 Playwright 嘅示例代碼:

await page.goto('https://example.com');
await page.getByText('登錄').click();
await expect(page).toHaveURL('/dashboard');

但係你唔知道:

  • ❌ page.goto() 點解要等待?
  • ❌ getByText() 和 getByRole() 有咩分別?
  • ❌ expect() 可以驗證啲乜嘢?
  • ❌ 測試失敗咗點樣除錯?

3. 想測試真實嘅項目,但係唔知點樣入手

你可能想測試自己公司嘅項目,或者好似 sogoodtool.com 噉樣嘅真實網站,但係:

  • ❌ 唔知點分析頁面結構
  • ❌ 唔知點設計測試用例
  • ❌ 唔知點處理各種互動場景

二、解決方案:用 playwright-cli Skill 寫第一個測試

今日同大家介紹 playwright-cli Skill,佢包含咗 Playwright 嘅基本能力:

playwright-cliSkill 包含咗啲乜?

┌─────────────────────────────────────────────────────────┐
│              playwright-cli Skill 核心能力                 │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  【瀏覽器啓動】                                           │
│  ├── 啓動 Chromium、Firefox、WebKit                      │
│  ├── 無頭模式 / 有頭模式                                 │
│  ├── 瀏覽器窗口大小設置                                   │
│  └── 多瀏覽器並行執行                                     │
│                                                         │
│  【頁面導航】                                             │
│  ├── 打開 URL(page.goto)                               │
│  ├── 頁面刷新(page.reload)                              │
│  ├── 前進後退(page.goBack / page.goForward)             │
│  └── 等待頁面加載(waitForLoadState)                      │
│                                                         │
│  【元素定位】                                             │
│  ├── getByRole(推薦)                                   │
│  ├── getByText                                           │
│  ├── getByLabel                                          │
│  ├── getByPlaceholder                                    │
│  ├── getByTestId                                         │
│  └── CSS / XPath(不推薦)                               │
│                                                         │
│  【元素交互】                                             │
│  ├── 點擊(click)                                       │
│  ├── 輸入(fill)                                        │
│  ├── 選擇(selectOption)                                │
│  ├── 勾選(check / uncheck)                             │
│  └── 鍵盤操作(press)                                   │
│                                                         │
│  【斷言驗證】                                             │
│  ├── URL 驗證(toHaveURL)                               │
│  ├── 標題驗證(toHaveTitle)                             │
│  ├── 可見性驗證(toBeVisible)                           │
│  ├── 文本驗證(toHaveText)                              │
│  ├── 屬性驗證(toHaveAttribute)                         │
│  └── 包含驗證(toContainText)                           │
│                                                         │
│  【等待機制】                                             │
│  ├── 等待元素可見(waitFor)                             │
│  ├── 等待網絡請求(waitForResponse)                     │
│  └── 等待導航(waitForNavigation)                        │
│                                                         │
│  【調試支持】                                             │
│  ├── 截圖(screenshot)                                  │
│  ├── 錄屏(video)                                       │
│  ├── 追蹤(trace)                                       │
│  └── Playwright Inspector                               │
│                                                         │
└─────────────────────────────────────────────────────────┘

元素定位優先級

playwright-cli Skill 強調咗一個非常重要嘅原則:元素定位優先級

┌─────────────────────────────────────────────────────────┐
│                    元素定位優先級                          │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  推薦程度從高到低:                                       │
│                                                         │
│  1. getByRole          ✅ 最推薦                         │
│     ├── 語義化定位,最穩定                               │
│     └── 例如:getByRole('button', { name: '登錄' })     │
│                                                         │
│  2. getByLabel         ✅ 推薦                           │
│     ├── 適用於表單輸入框                                 │
│     └── 例如:getByLabel('郵箱')                         │
│                                                         │
│  3. getByPlaceholder   ✅ 推薦                           │
│     ├── 適用於有 placeholder 的輸入框                     │
│     └── 例如:getByPlaceholder('請輸入郵箱')             │
│                                                         │
│  4. getByText          ✅ 推薦                           │
│     ├── 適用於文本內容                                   │
│     └── 例如:getByText('登錄成功')                      │
│                                                         │
│  5. getByTestId        ⚠️ 儘量用                        │
│     ├── 需要開發配合添加 data-testid                     │
│     └── 例如:getByTestId('login-button')               │
│                                                         │
│  6. CSS 選擇器          ❌ 不推薦                         │
│     ├── 容易受 CSS 類名變化影響                          │
│     └── 例如:page.locator('.login-btn')                │
│                                                         │
│  7. XPath              ❌ 不推薦                         │
│     ├── 最不穩定,容易受 DOM 結構變化影響                 │
│     └── 例如:page.locator('//button[text()="登錄"]')   │
│                                                         │
└─────────────────────────────────────────────────────────┘

三、真實案例:測試 sogoodtool.com 嘅登入功能

等我哋用 sogoodtool.com 嚟實際演練,寫一個完整嘅登入功能測試。

第一步:分析登入頁面

首先,等我哋睇嚇 sogoodtool.com 嘅登入頁面:

┌─────────────────────────────────────────────────────────┐
│                    sogoodtool.com 登錄頁面                 │
├─────────────────────────────────────────────────────────┤
│                                                         │
│              [sogoodtool 標誌]                          │
│                                                         │
│  郵箱:     [________________________________]           │
│             請輸入郵箱                                    │
│                                                         │
│  密碼:     [________________________________]           │
│             請輸入密碼                                    │
│                                                         │
│  [記住我]  忘記密碼?                                    │
│                                                         │
│  [                    登 錄                    ]         │
│                                                         │
│  還沒有賬號?[立即註冊]                                   │
│                                                         │
└─────────────────────────────────────────────────────────┘

第二步:設計測試用例

基於 playwright-cli Skill,我哋可以設計以下測試用例:

用例編號
測試場景
測試步驟
預期結果
TC001
頁面正常載入
打開登入頁面
頁面標題包含"登入",電郵同密碼輸入框可見
TC002
登入成功
輸入正確嘅電郵同密碼,撳登入
跳轉到 dashboard 頁面
TC003
登入失敗 - 密碼錯誤
輸入正確嘅電郵,錯誤嘅密碼
顯示"密碼錯誤"提示
TC004
登入失敗 - 用戶唔存在
輸入唔存在嘅電郵
顯示"用戶唔存在"提示
TC005
登入失敗 - 電郵留空
唔輸入電郵,撳登入
顯示"請輸入電郵"提示
TC006
登入失敗 - 密碼留空
輸入電郵,唔輸入密碼
顯示"請輸入密碼"提示

第三步:編寫測試代碼

創建 tests/login.spec.ts 文件:

// tests/login.spec.ts
import { test, expect } from '@playwright/test';

// 測試套件:登錄功能測試
test.describe('登錄功能測試', () => {

  // 每個測試用例執行前的操作
  test.beforeEach(async ({ page }) => {
    // 導航到登錄頁面
    await page.goto('https://sogoodtool.com/#/login');
    // 等待頁面加載完成
    await page.waitForLoadState('networkidle');
  });

  // TC001: 頁面正常加載
  test('頁面能夠正常加載', async ({ page }) => {
    // 驗證頁面標題
    await expect(page).toHaveTitle(/登錄/);

    // 驗證郵箱輸入框可見(通過 placeholder)
    await expect(page.getByPlaceholder('請輸入郵箱')).toBeVisible();

    // 驗證密碼輸入框可見
    await expect(page.getByPlaceholder('請輸入密碼')).toBeVisible();

    // 驗證登錄按鈕可見(通過 role)
    await expect(page.getByRole('button', { name: '登錄' })).toBeVisible();
  });

  // TC002: 登錄成功
  test('用戶可以成功登錄', async ({ page }) => {
    // 輸入郵箱(使用 getByPlaceholder)
    await page.getByPlaceholder('請輸入郵箱').fill('test@sogoodtool.com');

    // 輸入密碼
    await page.getByPlaceholder('請輸入密碼').fill('Test1234');

    // 點擊登錄按鈕(使用 getByRole)
    await page.getByRole('button', { name: '登錄' }).click();

    // 等待導航完成
    await page.waitForLoadState('networkidle');

    // 驗證跳轉到 dashboard
    await expect(page).toHaveURL(/dashboard/);
  });

  // TC003: 登錄失敗 - 密碼錯誤
  test('登錄失敗:密碼錯誤', async ({ page }) => {
    // 輸入正確的郵箱
    await page.getByPlaceholder('請輸入郵箱').fill('test@sogoodtool.com');

    // 輸入錯誤的密碼
    await page.getByPlaceholder('請輸入密碼').fill('WrongPassword');

    // 點擊登錄按鈕
    await page.getByRole('button', { name: '登錄' }).click();

    // 驗證顯示錯誤提示
    await expect(page.getByText('密碼錯誤')).toBeVisible();

    // 驗證沒有跳轉(仍然在登錄頁面)
    await expect(page).toHaveURL(/login/);
  });

  // TC004: 登錄失敗 - 用戶不存在
  test('登錄失敗:用戶不存在', async ({ page }) => {
    // 輸入不存在的郵箱
    await page.getByPlaceholder('請輸入郵箱').fill('nonexistent@sogoodtool.com');

    // 輸入任意密碼
    await page.getByPlaceholder('請輸入密碼').fill('Test1234');

    // 點擊登錄按鈕
    await page.getByRole('button', { name: '登錄' }).click();

    // 驗證顯示錯誤提示
    await expect(page.getByText('用戶不存在')).toBeVisible();
  });

  // TC005: 登錄失敗 - 郵箱為空
  test('登錄失敗:郵箱為空', async ({ page }) => {
    // 不輸入郵箱,直接輸入密碼
    await page.getByPlaceholder('請輸入密碼').fill('Test1234');

    // 點擊登錄按鈕
    await page.getByRole('button', { name: '登錄' }).click();

    // 驗證顯示錯誤提示
    await expect(page.getByText('請輸入郵箱')).toBeVisible();
  });

  // TC006: 登錄失敗 - 密碼為空
  test('登錄失敗:密碼為空', async ({ page }) => {
    // 輸入郵箱,不輸入密碼
    await page.getByPlaceholder('請輸入郵箱').fill('test@sogoodtool.com');

    // 點擊登錄按鈕
    await page.getByRole('button', { name: '登錄' }).click();

    // 驗證顯示錯誤提示
    await expect(page.getByText('請輸入密碼')).toBeVisible();
  });
});

第四步:執行測試

# 運行所有測試
npx playwright test

# 運行特定測試文件
npx playwright test tests/login.spec.ts

# 在 UI 模式下運行(可以看到瀏覽器操作)
npx playwright test tests/login.spec.ts --ui

# 只運行 Chromium
npx playwright test tests/login.spec.ts --project=chromium

第五步:睇測試報告

# 運行測試並生成 HTML 報告
npx playwright test tests/login.spec.ts --reporter=html

# 打開報告
npx playwright show-report

四、核心知識點總結

1. 頁面導航

// 基礎導航
await page.goto('https://sogoodtool.com/#/login');

// 等待頁面加載
await page.waitForLoadState('networkidle');

// 等待導航完成
await page.waitForNavigation();

// 頁面刷新
await page.reload();

// 前進後退
await page.goBack();
await page.goForward();

2. 元素定位(建議方式)

// 1. getByRole(最推薦)
await page.getByRole('button', { name: '登錄' }).click();
await page.getByRole('textbox', { name: '郵箱' }).fill('test@example.com');

// 2. getByPlaceholder(適用於輸入框)
await page.getByPlaceholder('請輸入郵箱').fill('test@example.com');
await page.getByPlaceholder('請輸入密碼').fill('Test1234');

// 3. getByText(適用於文本)
await expect(page.getByText('密碼錯誤')).toBeVisible();
await expect(page.getByText('用戶不存在')).toBeVisible();

// 4. getByLabel(適用於表單)
await page.getByLabel('郵箱').fill('test@example.com');
await page.getByLabel('記住我').check();

3. 元素互動

// 點擊
await page.getByRole('button', { name: '登錄' }).click();

// 輸入
await page.getByPlaceholder('請輸入郵箱').fill('test@example.com');

// 清空
await page.getByPlaceholder('請輸入郵箱').fill('');

// 選擇下拉框
await page.getByRole('combobox').selectOption('公開訪問');

// 勾選複選框
await page.getByLabel('記住我').check();

// 取消勾選
await page.getByLabel('記住我').uncheck();

// 鍵盤操作
await page.getByPlaceholder('請輸入密碼').press('Enter');

4. 斷言驗證

// URL 驗證
await expect(page).toHaveURL(/dashboard/);
await expect(page).toHaveURL('https://sogoodtool.com/#/dashboard');

// 標題驗證
await expect(page).toHaveTitle(/登錄/);

// 可見性驗證
await expect(page.getByText('密碼錯誤')).toBeVisible();
await expect(page.getByText('登錄成功')).toBeHidden();

// 文本驗證
await expect(page.getByRole('heading')).toHaveText('歡迎回來');

// 包含驗證
await expect(page.locator('.error-message')).toContainText('錯誤');

// 屬性驗證
await expect(page.getByRole('button', { name: '登錄' })).toBeEnabled();
await expect(page.getByRole('button', { name: '登錄' })).toBeDisabled();

5. 等待機制

// 等待元素可見
await page.getByText('登錄成功').waitFor();

// 等待指定時間(不推薦,但調試時有用)
await page.waitForTimeout(1000);

// 等待網絡請求
await page.waitForResponse('**/api/login');

// 等待導航
await page.waitForNavigation();

// 等待頁面加載狀態
await page.waitForLoadState('load');      // 等待 load 事件
await page.waitForLoadState('domcontentloaded');  // 等待 DOM 加載
await page.waitForLoadState('networkidle');  // 等待網絡空閒(推薦)

五、下一篇預告

恭喜你!而家你已經學識咗 點樣寫第一個 Playwright 自動化測試

下一篇文章,我會帶你解決一個更實際嘅問題:

【AI 測試 Skill 進階篇】03 | 穩健元素定位:UI 變更時測試唔會崩潰嘅秘訣

喺嗰篇文章入面,你會學到:

  • 點解 UI 一變,測試就全部死曬?
  • 咩係多備選定位器策略?
  • 點樣判斷元素係咪存在、係咪可見?
  • 如何用 playwright-robust-locators 點樣用 Skill 編寫穩健嘅測試?

敬請期待!


六、想更有系統咁學習?加入知識星球

你想得到啲乜?

今日同大家介紹嘅 playwright-cli Skill,只係 8 個 Playwright Skill 之中嘅一個。

如果你想:

  • ✅ 得到 完整嘅 8 個 Playwright Skill
  • ✅ 學習 playwright-robust-locators(穩健元素定位)
  • ✅ 得到 sogoodtool.com 完整嘅測試用例
  • ✅ 有問題可以隨時問
  • ✅ 持續學習更多測試乾貨

我推薦嘅 Skill

我整理咗 8 個完整嘅 Playwright 自動化測試 Skill

Skill
說明
難度
playwright-cli
Playwright 基本能力
入門
playwright-robust-locators
穩健元素定位
進階
playwright-core-features-testing
5 要素測試設計模式
進階
playwright-positive-negative-testing
正負面測試結合策略
進階
playwright-cli-url-docs-to-json-zh
自動生成測試用例
高級
playwright-cli-execute-stop-zh
測試執行與報告
高級
json-testcase-to-excel-zh
JSON 測試用例轉 Excel
高級
ai-testing-skill
完整嘅測試理論體系
體系

點樣得到?

呢啲 Skill 都已經放咗喺我嘅 「Bigtalk軟件測試進階」 知識星球入面喇。

掃瞄下面嘅QR code,加入知識星球,就可以得到:

  • ✅ 8 個完整嘅 Playwright 自動化測試 Skill
  • ✅ sogoodtool.com 完整嘅測試用例
  • ✅ 我會喺星球入面持續更新更多測試乾貨
  • ✅ 可以向我提問,我會喺星球入面解答
圖片

微信掃碼,加入「Bigtalk軟件測試進階」


想轉型做 AI 測試工程師?想有系統咁學習 Playwright 自動化測試?

掃瞄QR code,加入知識星球,開始你嘅進階之路! 🚀


下一篇:《【AI 測試 Skill 進階篇】03 | 穩健元素定位:UI 變更時測試唔會崩潰嘅秘訣》,敬請期待!


【AI 測試 Skill 入門篇】02 | 第一個自動化測試:sogoodtool.com 實戰案例

一、痛點:環境搭好了,但不知道怎麼開始寫測試

你是不是有這些困惑?

1. 環境搭好了,但不知道從哪下手

你可能已經完成了環境搭建:

  • ✅ Node.js 安裝好了
  • ✅ Playwright 安裝好了
  • ✅ Trae CN 也安裝好了

但一打開編輯器,就懵了:

  • ❌ 第一行代碼寫什麼?
  • ❌ 怎麼打開瀏覽器?
  • ❌ 怎麼定位元素?
  • ❌ 怎麼驗證結果?

2. 只會複製粘貼,不知道為什麼這樣寫

你可能在網上找到了一些 Playwright 的示例代碼:

await page.goto('https://example.com');
await page.getByText('登錄').click();
await expect(page).toHaveURL('/dashboard');

但你不知道:

  • ❌ page.goto() 為什麼要等待?
  • ❌ getByText() 和 getByRole() 有什麼區別?
  • ❌ expect() 可以驗證哪些東西?
  • ❌ 測試失敗了怎麼調試?

3. 想測試實際項目,但不知道怎麼入手

你可能想測試自己公司的項目,或者像 sogoodtool.com 這樣的實際網站,但:

  • ❌ 不知道怎麼分析頁面結構
  • ❌ 不知道怎麼設計測試用例
  • ❌ 不知道怎麼處理各種交互場景

二、解決方案:用 playwright-cli Skill 寫第一個測試

今天給大家介紹 playwright-cli Skill,它包含了 Playwright 的基礎能力:

playwright-cliSkill 包含什麼?

┌─────────────────────────────────────────────────────────┐
│              playwright-cli Skill 核心能力                 │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  【瀏覽器啓動】                                           │
│  ├── 啓動 Chromium、Firefox、WebKit                      │
│  ├── 無頭模式 / 有頭模式                                 │
│  ├── 瀏覽器窗口大小設置                                   │
│  └── 多瀏覽器並行執行                                     │
│                                                         │
│  【頁面導航】                                             │
│  ├── 打開 URL(page.goto)                               │
│  ├── 頁面刷新(page.reload)                              │
│  ├── 前進後退(page.goBack / page.goForward)             │
│  └── 等待頁面加載(waitForLoadState)                      │
│                                                         │
│  【元素定位】                                             │
│  ├── getByRole(推薦)                                   │
│  ├── getByText                                           │
│  ├── getByLabel                                          │
│  ├── getByPlaceholder                                    │
│  ├── getByTestId                                         │
│  └── CSS / XPath(不推薦)                               │
│                                                         │
│  【元素交互】                                             │
│  ├── 點擊(click)                                       │
│  ├── 輸入(fill)                                        │
│  ├── 選擇(selectOption)                                │
│  ├── 勾選(check / uncheck)                             │
│  └── 鍵盤操作(press)                                   │
│                                                         │
│  【斷言驗證】                                             │
│  ├── URL 驗證(toHaveURL)                               │
│  ├── 標題驗證(toHaveTitle)                             │
│  ├── 可見性驗證(toBeVisible)                           │
│  ├── 文本驗證(toHaveText)                              │
│  ├── 屬性驗證(toHaveAttribute)                         │
│  └── 包含驗證(toContainText)                           │
│                                                         │
│  【等待機制】                                             │
│  ├── 等待元素可見(waitFor)                             │
│  ├── 等待網絡請求(waitForResponse)                     │
│  └── 等待導航(waitForNavigation)                        │
│                                                         │
│  【調試支持】                                             │
│  ├── 截圖(screenshot)                                  │
│  ├── 錄屏(video)                                       │
│  ├── 追蹤(trace)                                       │
│  └── Playwright Inspector                               │
│                                                         │
└─────────────────────────────────────────────────────────┘

元素定位優先級

playwright-cli Skill 強調了一個非常重要的原則:元素定位優先級

┌─────────────────────────────────────────────────────────┐
│                    元素定位優先級                          │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  推薦程度從高到低:                                       │
│                                                         │
│  1. getByRole          ✅ 最推薦                         │
│     ├── 語義化定位,最穩定                               │
│     └── 例如:getByRole('button', { name: '登錄' })     │
│                                                         │
│  2. getByLabel         ✅ 推薦                           │
│     ├── 適用於表單輸入框                                 │
│     └── 例如:getByLabel('郵箱')                         │
│                                                         │
│  3. getByPlaceholder   ✅ 推薦                           │
│     ├── 適用於有 placeholder 的輸入框                     │
│     └── 例如:getByPlaceholder('請輸入郵箱')             │
│                                                         │
│  4. getByText          ✅ 推薦                           │
│     ├── 適用於文本內容                                   │
│     └── 例如:getByText('登錄成功')                      │
│                                                         │
│  5. getByTestId        ⚠️ 儘量用                        │
│     ├── 需要開發配合添加 data-testid                     │
│     └── 例如:getByTestId('login-button')               │
│                                                         │
│  6. CSS 選擇器          ❌ 不推薦                         │
│     ├── 容易受 CSS 類名變化影響                          │
│     └── 例如:page.locator('.login-btn')                │
│                                                         │
│  7. XPath              ❌ 不推薦                         │
│     ├── 最不穩定,容易受 DOM 結構變化影響                 │
│     └── 例如:page.locator('//button[text()="登錄"]')   │
│                                                         │
└─────────────────────────────────────────────────────────┘

三、實際案例:測試 sogoodtool.com 的登錄功能

讓我們用 sogoodtool.com 來實際演練,寫一個完整的登錄功能測試。

第一步:分析登錄頁面

首先,讓我們看看 sogoodtool.com 的登錄頁面:

┌─────────────────────────────────────────────────────────┐
│                    sogoodtool.com 登錄頁面                 │
├─────────────────────────────────────────────────────────┤
│                                                         │
│              [sogoodtool 標誌]                          │
│                                                         │
│  郵箱:     [________________________________]           │
│             請輸入郵箱                                    │
│                                                         │
│  密碼:     [________________________________]           │
│             請輸入密碼                                    │
│                                                         │
│  [記住我]  忘記密碼?                                    │
│                                                         │
│  [                    登 錄                    ]         │
│                                                         │
│  還沒有賬號?[立即註冊]                                   │
│                                                         │
└─────────────────────────────────────────────────────────┘

第二步:設計測試用例

基於 playwright-cli Skill,我們可以設計以下測試用例:

用例編號
測試場景
測試步驟
預期結果
TC001
頁面正常加載
打開登錄頁面
頁面標題包含"登錄",郵箱和密碼輸入框可見
TC002
登錄成功
輸入正確郵箱和密碼,點擊登錄
跳轉到 dashboard 頁面
TC003
登錄失敗 - 密碼錯誤
輸入正確郵箱,錯誤密碼
顯示"密碼錯誤"提示
TC004
登錄失敗 - 用戶不存在
輸入不存在的郵箱
顯示"用戶不存在"提示
TC005
登錄失敗 - 郵箱為空
不輸入郵箱,點擊登錄
顯示"請輸入郵箱"提示
TC006
登錄失敗 - 密碼為空
輸入郵箱,不輸入密碼
顯示"請輸入密碼"提示

第三步:編寫測試代碼

創建 tests/login.spec.ts 文件:

// tests/login.spec.ts
import { test, expect } from '@playwright/test';

// 測試套件:登錄功能測試
test.describe('登錄功能測試', () => {

  // 每個測試用例執行前的操作
  test.beforeEach(async ({ page }) => {
    // 導航到登錄頁面
    await page.goto('https://sogoodtool.com/#/login');
    // 等待頁面加載完成
    await page.waitForLoadState('networkidle');
  });

  // TC001: 頁面正常加載
  test('頁面能夠正常加載', async ({ page }) => {
    // 驗證頁面標題
    await expect(page).toHaveTitle(/登錄/);

    // 驗證郵箱輸入框可見(通過 placeholder)
    await expect(page.getByPlaceholder('請輸入郵箱')).toBeVisible();

    // 驗證密碼輸入框可見
    await expect(page.getByPlaceholder('請輸入密碼')).toBeVisible();

    // 驗證登錄按鈕可見(通過 role)
    await expect(page.getByRole('button', { name: '登錄' })).toBeVisible();
  });

  // TC002: 登錄成功
  test('用戶可以成功登錄', async ({ page }) => {
    // 輸入郵箱(使用 getByPlaceholder)
    await page.getByPlaceholder('請輸入郵箱').fill('test@sogoodtool.com');

    // 輸入密碼
    await page.getByPlaceholder('請輸入密碼').fill('Test1234');

    // 點擊登錄按鈕(使用 getByRole)
    await page.getByRole('button', { name: '登錄' }).click();

    // 等待導航完成
    await page.waitForLoadState('networkidle');

    // 驗證跳轉到 dashboard
    await expect(page).toHaveURL(/dashboard/);
  });

  // TC003: 登錄失敗 - 密碼錯誤
  test('登錄失敗:密碼錯誤', async ({ page }) => {
    // 輸入正確的郵箱
    await page.getByPlaceholder('請輸入郵箱').fill('test@sogoodtool.com');

    // 輸入錯誤的密碼
    await page.getByPlaceholder('請輸入密碼').fill('WrongPassword');

    // 點擊登錄按鈕
    await page.getByRole('button', { name: '登錄' }).click();

    // 驗證顯示錯誤提示
    await expect(page.getByText('密碼錯誤')).toBeVisible();

    // 驗證沒有跳轉(仍然在登錄頁面)
    await expect(page).toHaveURL(/login/);
  });

  // TC004: 登錄失敗 - 用戶不存在
  test('登錄失敗:用戶不存在', async ({ page }) => {
    // 輸入不存在的郵箱
    await page.getByPlaceholder('請輸入郵箱').fill('nonexistent@sogoodtool.com');

    // 輸入任意密碼
    await page.getByPlaceholder('請輸入密碼').fill('Test1234');

    // 點擊登錄按鈕
    await page.getByRole('button', { name: '登錄' }).click();

    // 驗證顯示錯誤提示
    await expect(page.getByText('用戶不存在')).toBeVisible();
  });

  // TC005: 登錄失敗 - 郵箱為空
  test('登錄失敗:郵箱為空', async ({ page }) => {
    // 不輸入郵箱,直接輸入密碼
    await page.getByPlaceholder('請輸入密碼').fill('Test1234');

    // 點擊登錄按鈕
    await page.getByRole('button', { name: '登錄' }).click();

    // 驗證顯示錯誤提示
    await expect(page.getByText('請輸入郵箱')).toBeVisible();
  });

  // TC006: 登錄失敗 - 密碼為空
  test('登錄失敗:密碼為空', async ({ page }) => {
    // 輸入郵箱,不輸入密碼
    await page.getByPlaceholder('請輸入郵箱').fill('test@sogoodtool.com');

    // 點擊登錄按鈕
    await page.getByRole('button', { name: '登錄' }).click();

    // 驗證顯示錯誤提示
    await expect(page.getByText('請輸入密碼')).toBeVisible();
  });
});

第四步:運行測試

# 運行所有測試
npx playwright test

# 運行特定測試文件
npx playwright test tests/login.spec.ts

# 在 UI 模式下運行(可以看到瀏覽器操作)
npx playwright test tests/login.spec.ts --ui

# 只運行 Chromium
npx playwright test tests/login.spec.ts --project=chromium

第五步:查看測試報告

# 運行測試並生成 HTML 報告
npx playwright test tests/login.spec.ts --reporter=html

# 打開報告
npx playwright show-report

四、核心知識點總結

1. 頁面導航

// 基礎導航
await page.goto('https://sogoodtool.com/#/login');

// 等待頁面加載
await page.waitForLoadState('networkidle');

// 等待導航完成
await page.waitForNavigation();

// 頁面刷新
await page.reload();

// 前進後退
await page.goBack();
await page.goForward();

2. 元素定位(推薦方式)

// 1. getByRole(最推薦)
await page.getByRole('button', { name: '登錄' }).click();
await page.getByRole('textbox', { name: '郵箱' }).fill('test@example.com');

// 2. getByPlaceholder(適用於輸入框)
await page.getByPlaceholder('請輸入郵箱').fill('test@example.com');
await page.getByPlaceholder('請輸入密碼').fill('Test1234');

// 3. getByText(適用於文本)
await expect(page.getByText('密碼錯誤')).toBeVisible();
await expect(page.getByText('用戶不存在')).toBeVisible();

// 4. getByLabel(適用於表單)
await page.getByLabel('郵箱').fill('test@example.com');
await page.getByLabel('記住我').check();

3. 元素交互

// 點擊
await page.getByRole('button', { name: '登錄' }).click();

// 輸入
await page.getByPlaceholder('請輸入郵箱').fill('test@example.com');

// 清空
await page.getByPlaceholder('請輸入郵箱').fill('');

// 選擇下拉框
await page.getByRole('combobox').selectOption('公開訪問');

// 勾選複選框
await page.getByLabel('記住我').check();

// 取消勾選
await page.getByLabel('記住我').uncheck();

// 鍵盤操作
await page.getByPlaceholder('請輸入密碼').press('Enter');

4. 斷言驗證

// URL 驗證
await expect(page).toHaveURL(/dashboard/);
await expect(page).toHaveURL('https://sogoodtool.com/#/dashboard');

// 標題驗證
await expect(page).toHaveTitle(/登錄/);

// 可見性驗證
await expect(page.getByText('密碼錯誤')).toBeVisible();
await expect(page.getByText('登錄成功')).toBeHidden();

// 文本驗證
await expect(page.getByRole('heading')).toHaveText('歡迎回來');

// 包含驗證
await expect(page.locator('.error-message')).toContainText('錯誤');

// 屬性驗證
await expect(page.getByRole('button', { name: '登錄' })).toBeEnabled();
await expect(page.getByRole('button', { name: '登錄' })).toBeDisabled();

5. 等待機制

// 等待元素可見
await page.getByText('登錄成功').waitFor();

// 等待指定時間(不推薦,但調試時有用)
await page.waitForTimeout(1000);

// 等待網絡請求
await page.waitForResponse('**/api/login');

// 等待導航
await page.waitForNavigation();

// 等待頁面加載狀態
await page.waitForLoadState('load');      // 等待 load 事件
await page.waitForLoadState('domcontentloaded');  // 等待 DOM 加載
await page.waitForLoadState('networkidle');  // 等待網絡空閒(推薦)

五、下一篇預告

恭喜你!現在你已經學會了 如何寫第一個 Playwright 自動化測試

下一篇文章,我將帶你解決一個更實際的問題:

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

在那篇文章中,你將學到:

  • 為什麼 UI 一變,測試就全掛?
  • 什麼是多備選定位器策略?
  • 如何判斷元素是否存在、是否可見?
  • 如何用 playwright-robust-locators Skill 編寫健壯的測試?

敬請期待!


六、想更系統地學習?加入知識星球

你想獲得什麼?

今天給大家介紹的 playwright-cli Skill,只是 8 個 Playwright Skill 中的一個。

如果你想:

  • ✅ 獲得 完整的 8 個 Playwright Skill
  • ✅ 學習 playwright-robust-locators(健壯元素定位)
  • ✅ 獲得 sogoodtool.com 完整的測試用例
  • ✅ 有問題可以隨時提問
  • ✅ 持續學習更多測試乾貨

我推薦的 Skill

我整理了 8 個完整的 Playwright 自動化測試 Skill

Skill
說明
難度
playwright-cli
Playwright 基礎能力
入門
playwright-robust-locators
健壯元素定位
進階
playwright-core-features-testing
5 要素測試設計模式
進階
playwright-positive-negative-testing
正負面測試結合策略
進階
playwright-cli-url-docs-to-json-zh
自動生成測試用例
高級
playwright-cli-execute-stop-zh
測試執行與報告
高級
json-testcase-to-excel-zh
JSON 測試用例轉 Excel
高級
ai-testing-skill
完整的測試理論體系
體系

如何獲取?

這些 Skill 都已經放在我的 「Bigtalk軟件測試進階」 知識星球裏了。

掃描下方二維碼,加入知識星球,即可獲得:

  • ✅ 8 個完整的 Playwright 自動化測試 Skill
  • ✅ sogoodtool.com 完整的測試用例
  • ✅ 我會在星球裏持續更新更多測試乾貨
  • ✅ 可以向我提問,我會在星球裏解答
圖片

微信掃碼,加入「Bigtalk軟件測試進階」


想轉型 AI 測試工程師?想系統地學習 Playwright 自動化測試?

掃描二維碼,加入知識星球,開始你的進階之路! 🚀


下一篇:《【AI 測試 Skill 進階篇】03 | 健壯元素定位:UI 變更時測試不崩潰的秘訣》,敬請期待!