Bỏ qua

Module 04: Locator Strategy — Nghệ Thuật Bắt Element Ổn Định

🎯 Mục Tiêu Module

  • Hiểu tại sao Locator quan trọng trong automation test
  • Nắm được Locator Hierarchy (thứ tự ưu tiên)
  • Thực hành tìm và đánh giá locator trên website thực
  • Biết cách fallback khi locator chính không có

4.1. Tại Sao Locator Quan Trong?

Vấn đề: Locator không ổn định

┌─────────────────────────────────────────────────────┐
│                                                     │
│  Locator động (thay đổi mỗi lần load):             │
│  <div id="ember123">...</div>                       │
│  <div id="ember456">...</div>  ← ID thay đổi!     │
│                                                     │
│  → Code gãy mỗi lần chạy                            │
│  → Maintenance tốn thời gian                        │
│  → Test không tin cậy                               │
└─────────────────────────────────────────────────────┘

Giải pháp: Locator ổn định

┌─────────────────────────────────────────────────────┐
│                                                     │
│  Locator ổn định:                                   │
│  <button data-testid="login-btn">Login</button>     │
│                                                     │
│  → Code chạy ổn định                                │
│  → Maintenance ít                                    │
│  → Test tin cậy                                     │
└─────────────────────────────────────────────────────┘

4.2. Locator Hierarchy — Thứ Tự Ưu Tiên

┌─────────────────────────────────────────────────────┐
│  LOCATOR HIERARCHY                                  │
│                                                     │
│  Ưu tiên 1: [data-testid="xxx"]                    │
│  → Ổn định cao nhất, dành riêng cho test           │
│                                                     │
│  Ưu tiên 2: [data-cy="xxx"]                        │
│  → Cypress convention, cũng rất ổn                  │
│                                                     │
│  Ưu tiên 3: [id="xxx"] (cố định)                   │
│  → Chỉ khi ID không phải dynamic                   │
│                                                     │
│  Ưu tiên 4: [aria-label="xxx"]                     │
│  → Accessibility-friendly                           │
│                                                     │
│  Ưu tiên 5: text content                            │
│  → Dễ đọc nhưng dễ thay đổi                        │
│                                                     │
│  Ưu tiên 6: CSS selector                            │
│  → Class-based, có thể thay khi refactor UI         │
│                                                     │
│  Ưu tiên 7: XPath                                   │
│  → Last resort, chỉ dùng khi bất khả kháng         │
└─────────────────────────────────────────────────────┘

Bảng chi tiết

Ưu tiên Locator Type Ví dụ Ổn định Dễ đọc
1 data-testid [data-testid="login-btn"] ⭐⭐⭐⭐⭐ ⭐⭐⭐
2 data-cy [data-cy="login-btn"] ⭐⭐⭐⭐⭐ ⭐⭐⭐
3 id (cố định) #login-btn ⭐⭐⭐⭐ ⭐⭐⭐⭐
4 aria-label [aria-label="Login"] ⭐⭐⭐⭐ ⭐⭐⭐⭐
5 text content text=Login ⭐⭐⭐ ⭐⭐⭐⭐⭐
6 CSS selector .login-button ⭐⭐ ⭐⭐⭐
7 XPath //button[@type='submit'] ⭐⭐

4.3. Cách Tìm Locator

Cách 1: Dùng Browser DevTools

  1. Mở DevTools (F12)
  2. Click vào element
  3. Xem Attributes trong Elements panel
┌─────────────────────────────────────────────────────┐
│  <button                                           │
│    data-testid="login-btn"    ← Ưu tiên 1          │
│    id="login-button"          ← Ưu tiên 3          │
│    class="btn btn-primary"    ← Ưu tiên 6          │
│    aria-label="Login"         ← Ưu tiên 4          │
│  >                                                  │
│    Login                                            │
│  </button>                                          │
└─────────────────────────────────────────────────────┘

Cách 2: Dùng Playwright Inspector

  1. Chạy code với --debug flag
  2. Dùng "Pick Locator" để chọn element
  3. Playwright sẽ gợi ý locator tốt nhất

Cách 3: Dùng Antigravity IDE

  1. Click vào element trên browser trong IDE
  2. IDE sẽ hiển thị locator được sử dụng
  3. Xem và đánh giá locator

4.4. Ví Dụ Thực Tế trên Practice Website

Trang Login: https://practice.automationtesting.in/my-account/

<!-- Ô Username -->
<input
  type="text"
  name="username"
  id="username"
  placeholder="Username"
  class="input-text"
/>

<!-- Ô Password -->
<input
  type="password"
  name="password"
  id="password"
  placeholder="Password"
  class="input-text"
/>

<!-- Nút Login -->
<button
  type="submit"
  name="login"
  class="button"
  value="Login"
>
  Login
</button>

Đánh giá locator cho trang Login

Element Locator tốt nhất Tại sao
Username #username ID cố định, dễ tìm
Password #password ID cố định, dễ tìm
Nút Login [name="login"] Name cố định

Code Playwright cho trang Login

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

test('test login', async ({ page }) => {
  await page.goto('https://practice.automationtesting.in/my-account/');

  // Dùng ID (ổn định)
  await page.locator('#username').fill('testuser123');
  await page.locator('#password').fill('Test@123456');

  // Dùng name attribute (ổn định)
  await page.locator('[name="login"]').click();

  // Assertion
  await expect(page.locator('.woocommerce-MyAccount-content')).toBeVisible();
});

4.5. Khi Nào Dùng Fallback?

Tình huống: Không có data-testid

Website không có data-testid:
<button class="btn-primary">Add to Cart</button>

Chiến lược Fallback

Không có data-testid?
    ├── Có ID cố định? ──► Dùng ID
    ├── Có aria-label? ──► Dùng aria-label
    ├── Có text content? ──► Dùng text
    │   (Chỉ khi text không thay đổi)
    └── Dùng CSS selector
        (Class-based, có thể thay khi refactor)

Ví dụ Fallback

// Ưu tiên 1: data-testid (không có)
// await page.locator('[data-testid="add-to-cart"]').click();

// Ưu tiên 2: ID (không có)
// await page.locator('#add-to-cart').click();

// Ưu tiên 3: aria-label (không có)
// await page.locator('[aria-label="Add to Cart"]').click();

// Ưu tiên 4: text content (có!)
await page.locator('text=Add to basket').click();

// Ưu tiên 5: CSS selector (fallback cuối)
// await page.locator('.add_to_cart_button').click();

4.6. Locator Anti-patterns

❌ Anti-pattern 1: Locator quá dài

// Quá dài, khó maintain
await page.locator('div.container > div.row > div.col-md-6 > form > div.form-group > input#email').fill('test@example.com');

// Nên dùng
await page.locator('#email').fill('test@example.com');

❌ Anti-pattern 2: Dùng index

// Dùng index → Gãy khi thứ tự thay đổi
await page.locator('button').nth(2).click();

// Nên dùng locator cụ thể
await page.locator('button:has-text("Submit")').click();

❌ Anti-pattern 3: Dùng XPath dài

// XPath dài, khó đọc
await page.locator('//div[@class="container"]/div[2]/form//button[@type="submit"]').click();

// Nên dùng CSS hoặc text
await page.locator('button[type="submit"]').click();

❌ Anti-pattern 4: Dùng waitForTimeout

// Chờ cố định → Không ổn định
await page.waitForTimeout(5000);

// Nên chờ element xuất hiện
await page.locator('#result').waitFor({ state: 'visible' });

4.7. Yêu Cầu Dev Thêm data-testid

Khi nào cần yêu cầu?

Website có data-testid? ──► Không cần yêu cầu
Website không có data-testid? ──► Xem xét yêu cầu

Cách yêu cầu

Gửi yêu cầu cho Dev team:

"Để automation test ổn định hơn, cần thêm attribute
data-testid cho các element quan trọng:

- Nút Login: data-testid="login-btn"
- Ô Username: data-testid="username-input"
- Ô Password: data-testid="password-input"
- Form: data-testid="login-form"

Đây là convention tốt cho testing, không ảnh hưởng
đến functionality của website."

Lợi ích

Bên Lợi ích
QC Test ổn định, ít maintenance
Dev Không ảnh hưởng code, dễ implement
Team CI/CD chạy ổn định

📝 Bài Tập

Bài Tập 1: Tìm Locator trên Practice Website

  1. Mở https://practice.automationtesting.in/my-account/
  2. Dùng DevTools tìm locator cho:
  3. Ô Username
  4. Ô Password
  5. Nút Login
  6. Link "Register"
  7. Đánh giá ổn định cho mỗi locator

Bài Tập 2: Đánh Giá Locator

Cho đoạn HTML sau, chọn locator tốt nhất:

<button
  data-testid="submit-order"
  id="btn-submit"
  class="btn btn-success"
  aria-label="Submit Order"
>
  Place Order
</button>

Bài Tập 3: Viết Code với Locator Ưu Tiên

Viết code Playwright cho flow đăng ký tài khoản:

  • URL: https://practice.automationtesting.in/my-account/
  • Chọn tab "Register"
  • Nhập email, password
  • Click nút Register
  • Tuân thủ Locator Hierarchy

✅ Checklist Hoàn Thành Module

  • [ ] Hiểu tại sao Locator quan trọng
  • [ ] Nắm được Locator Hierarchy
  • [ ] Biết cách tìm locator bằng DevTools
  • [ ] Thực hành tìm locator trên Practice Website
  • [ ] Biết cách dùng fallback
  • [ ] Nắm các anti-pattern cần tránh
  • [ ] Hoàn thành bài tập