NỘI DUNG BÀI HỌC

✅ Hiểu XPath là gì và tại sao gọi nó là vũ khí "hạng nặng" cuối cùng. ✅ Phân biệt XPath Tuyệt đối (Tuyệt đối tránh xa) và XPath Tương đối (Khuyên dùng). ✅ Bỏ túi "bảng cửu chương" cú pháp XPath từ cơ bản đến nâng cao. ✅ (QUAN TRỌNG) Làm chủ "Hệ tư tưởng Gia phả": Lội ngược dòng (Ancestor, Parent) và tìm kiếm anh em họ hàng (Sibling, Following). ✅ Viết kịch bản tổng hợp sử dụng XPath trong Playwright.

🧠 I. KHÁI NIỆM XPATH

 

👀 1️⃣ XPath là gì?

Ở Bài 2, chúng ta đã học get_by_* (tìm theo góc nhìn người dùng) và CSS Selector (tìm siêu tốc). Vậy XPath (XML Path Language) là gì? Hãy tưởng tượng nó là một chiếc Hệ thống định vị GPS cực kỳ phức tạp có thể bấu víu vào bất kỳ manh mối nhỏ nào để chỉ đường cho Robot Playwright.

💡 Sự thật phũ phàng: XPath chạy chậm hơn CSS một chút xíu và nhìn code khá "lằng nhằng". Bạn chỉ nên dùng XPath khi CSS và các hàm get_by_* đều bó tay!

Vậy tại sao phải học XPath? Vì nó có 2 siêu năng lực mà CSS không thể làm được:

  1. Tìm theo chữ ẩn sâu (Text): Tìm một thẻ chứa chữ kết hợp với nhiều điều kiện siêu phức tạp.

  2. Định vị theo Gia phả (Độc quyền): Khả năng đi từ phần tử này, chiếu sang phần tử khác (Từ Con nhìn lên Cha, từ Anh tìm ra Em).


🎯 II. XPATH TUYỆT ĐỐI VS XPATH TƯƠNG ĐỐI

Nếu coi XPath là bản đồ chỉ đường, chúng ta có 2 cách chỉ:

 

1️⃣ ❌ XPath Tuyệt đối (Absolute XPath) - TUYỆT ĐỐI TRÁNH XA!

  • Đặc điểm: Bắt đầu bằng một dấu gạch chéo /. Nó chỉ đường từ gốc rễ trên cùng của trang web đi xuống từng bậc một.

  • Ví dụ: /html/body/div[2]/div[1]/form/input[3]

  • 💡 Bình dân học vụ: Giống như chỉ đường: "Từ cổng thành, đi thẳng 2 ngã tư, rẽ trái, vào hẻm 1, gõ cửa nhà số 3". Trông thì có vẻ chính xác, nhưng nếu ngày mai ủy ban phường đập hẻm xây đường mới (Dev thay đổi giao diện), Robot sẽ lạc đường và kịch bản sẽ Fail đỏ lòm!


2️⃣ ✅ XPath Tương đối (Relative XPath) - CHÂN ÁI LÀ ĐÂY!

  • Đặc điểm: Bắt đầu bằng hai dấu gạch chéo //. Bỏ qua gốc rễ, "nhảy dù" thẳng xuống nơi có phần tử cần tìm.

  • Ví dụ: //input[@id='email']

  • 💡 Bình dân học vụ: Giống như gọi taxi: "Chở tôi đến thẳng cái nhà có số id là 'email'". Kệ cho Dev có bứng cái nhà đó đi đâu, Robot vẫn tìm được!


🏛️ III. "BẢNG CỬU CHƯƠNG" CÚ PHÁP XPATH CƠ BẢN

Để chuyển đổi từ CSS sang XPath, bạn chỉ cần nhớ công thức cốt lõi này: 👉 //TênThẻ[@ThuộcTính='Giá Trị']

Loại tìm kiếm Mã HTML thực tế Tìm bằng XPath Tương đối
Theo ID <input id="user"> //input[@id='user']
Theo Class <button class="btn"> //button[@class='btn']
Bất kỳ thuộc tính nào <input name="pwd"> //input[@name='pwd']
Chứa một phần (Contains) <div class="btn-login-123"> //div[contains(@class, 'btn-login')] (Bỏ qua dãy số 123 lằng nhằng)
Theo chữ hiển thị (Text) <a href="#">Quên mật khẩu</a> //a[text()='Quên mật khẩu']

 

🧭 IV. ĐỈNH CAO XPATH: ĐỊNH VỊ THEO "GIA PHẢ" (XPATH AXES)

Đây chính là linh hồn của XPath. Hãy dùng nó khi: Phần tử bạn muốn thao tác KHÔNG CÓ id/class rõ ràng, nhưng nó lại nằm cạnh một phần tử rất dễ tìm. Ta sẽ tìm phần tử dễ trước, rồi từ đó làm "bàn đạp" chiếu sang phần tử khó!

Để hiểu rõ cách XPath lội ngược, lội xuôi, chúng ta hãy coi cấu trúc HTML như một Cây Gia Phả. Hãy nhìn vào ví dụ sau, giả sử chúng ta lấy thẻ <span class="name">Nguyễn Văn A</span> làm BẢN THÂN (Bàn đạp) để đi tìm những người họ hàng xung quanh:

 

🧪 Cây Gia Phả HTML:

HTML
<div class="user-card">  <!-- 👴 TỔ TIÊN (Ông Nội): Chứa tất cả mọi người -->
    
    <h3>Hồ sơ</h3>       <!-- 🧔 BÁC: Khác cha, nằm trên -->
    
    <div class="details"> <!-- 👨 CHA RUỘT: Ôm trực tiếp các con vào lòng -->
        
        <label>Tên:</label>                           <!-- 👦 ANH RUỘT (Sinh trước) -->
        <span class="name">Nguyễn Văn A</span>        <!-- 🎯 BẢN THÂN (Làm bàn đạp) -->
        <button class="btn-edit">Sửa</button>         <!-- 👶 EM RUỘT (Sinh sau) -->
        
    </div>
    
    <div class="footer"> <!-- 👨 CHÚ: Khác cha, nằm dưới -->
        <button class="btn-delete">Xóa</button>       <!-- 🏃 NGƯỜI NỐI GÓT (Following) -->
    </div>

</div>

Chúng ta chia các từ khóa (Axes) thành 4 nhóm hướng đi. Cú pháp chung luôn là: 👉 //Bàn_Đạp/từ_khóa::Tên_Thẻ


🕵️‍♂️ NHÓM 1: NHÌN SANG NGANG (TÌM ANH EM RUỘT)

Điều kiện để làm anh em ruột: Phải nằm chung trong lòng một người Cha (thẻ bao bọc).

Từ khóa XPath Ý nghĩa (Ngôn ngữ Bình Dân) Ví dụ / Cách Robot di chuyển
following-sibling:: Tìm EM RUỘT: Tìm những thẻ cùng chung 1 Cha, nhưng nằm bên dưới (đẻ sau) Bản thân.

Đứng từ "Nguyễn Văn A", tìm nút "Sửa":


//span[text()='Nguyễn Văn A']/following-sibling::button


(Chiến thuật: Dùng khi Nhãn/Tên dễ tìm, còn ô nhập/nút bấm nằm kế bên thì bị ẩn danh).

preceding-sibling:: Tìm ANH RUỘT: Tìm những thẻ cùng chung 1 Cha, nhưng nằm bên trên (đẻ trước) Bản thân.

Đứng từ "Nguyễn Văn A", tìm ngược lên cái nhãn "Tên:":


//span[text()='Nguyễn Văn A']/preceding-sibling::label


(Chiến thuật: Hay dùng cho Checkbox nằm trước tên).

🕵️‍♂️ NHÓM 2: LỘI NGƯỢC DÒNG (TÌM BỀ TRÊN)

Độc chiêu của XPath, thứ mà CSS Selector không bao giờ làm được!

Từ khóa XPath Ý nghĩa (Ngôn ngữ Bình Dân) Ví dụ / Cách Robot di chuyển
parent::

Tìm CHA RUỘT: Lùi lên đúng 1 cấp, tóm lấy thẻ ôm trực tiếp Bản thân.


(Có thể viết tắt bằng /..)

Đứng từ "Nguyễn Văn A", tìm lên cái thẻ div .details chứa nó:


//span[text()='Nguyễn Văn A']/parent::div


Hoặc viết tắt: //span[text()='Nguyễn Văn A']/..

ancestor:: Tìm TỔ TIÊN: Lùi lên nhiều cấp (Cha, Ông Nội, Cố...). Tìm lớp vỏ bao bọc ngoài cùng.

Đứng từ "Nguyễn Văn A", tóm lấy toàn bộ thẻ bự .user-card (Ông nội):


//span[text()='Nguyễn Văn A']/ancestor::div[@class='user-card']


(Chiến thuật: Cực kỳ hữu dụng để tóm gọn cả 1 Table/Grid).

 

🕵️‍♂️ NHÓM 3: ĐI XUYÊN MÀN ĐÊM (KHÔNG CẦN CÙNG CHA)

Dùng khi phần tử muốn tìm nằm ở một nhánh khác, nhưng chắc chắn xuất hiện trước/sau Bản thân.

Từ khóa XPath Ý nghĩa (Ngôn ngữ Bình Dân) Ví dụ / Cách Robot di chuyển
following:: Người nối gót: Tìm TẤT CẢ thẻ xuất hiện phía sau Bản thân trong mã HTML.

Đứng từ "Nguyễn Văn A", nhìn xuyên nhánh để tóm nút "Xóa":


//span[text()='Nguyễn Văn A']/following::button[text()='Xóa']

preceding:: Người đi trước: Tìm TẤT CẢ thẻ xuất hiện phía trước Bản thân trong mã HTML.

Đứng từ nút "Xóa", nhìn ngược lên trên tìm chữ "Hồ sơ":


//button[text()='Xóa']/preceding::h3


🕵️‍♂️ NHÓM 4: NHÌN XUỐNG DƯỚI (TÌM CON CHÁU)

Bạn có thể viết tắt bằng dấu / hoặc // cho gọn.

Từ khóa XPath Ý nghĩa (Ngôn ngữ Bình Dân) Tương đương với cách viết tắt
child:: Tìm Con ruột: Nằm ngay dưới bụng 1 cấp.

Viết dài: //div[@class='details']/child::button


Viết tắt: //div[@class='details']/button

descendant:: Tìm Con Cháu: Nằm bên trong lòng, bất kể mấy cấp.

Viết dài: //div[@class='user-card']/descendant::button


Viết tắt: //div[@class='user-card']//button

 


🧾 V. VÍ DỤ THỰC CHIẾN: ĐƯA "GIA PHẢ" VÀO PLAYWRIGHT

Hãy xem xét bài toán Quản lý nhân sự: Có rất nhiều nút Xóa giống hệt nhau, làm sao để bấm đúng nút Xóa của "Nguyễn Văn A"?

 

🧪 Cấu trúc HTML (Giả lập):

HTML
<div class="user-row">
    <span class="name">Nguyễn Văn A</span>
    <span class="role">Tester</span>
    <button class="btn-delete">Xóa</button>
</div>
<div class="user-row">
    <span class="name">Trần Văn B</span>
    <span class="role">Dev</span>
    <button class="btn-delete">Xóa</button>
</div>

 

🧩 Kịch bản Playwright Python giải quyết bài toán:

from playwright.sync_api import Page

def test_xpath_gia_pha(page: Page):
    page.goto("https://admin-example.com")
    
    # -------------------------------------------------------------
    # 1. TUYỆT CHIÊU "EM RUỘT" (following-sibling)
    # BÀI TOÁN: Xóa Nguyễn Văn A
    # CHIẾN THUẬT: Lấy chữ "Nguyễn Văn A" làm Bàn Đạp, nhìn sang 
    # thằng "Em ruột" mang thẻ button bên dưới để click!
    # -------------------------------------------------------------
    nut_xoa_A = page.locator("//span[text()='Nguyễn Văn A']/following-sibling::button")
    nut_xoa_A.click()
    
    
    # -------------------------------------------------------------
    # 2. TUYỆT CHIÊU "CHA RUỘT" (parent:: hoặc /..)
    # BÀI TOÁN: Lấy toàn bộ thông tin của Trần Văn B
    # CHIẾN THUẬT: Đứng từ "Trần Văn B", lùi ra ngoài (tìm Cha ruột) 
    # để tóm trọn cái thẻ <div class="user-row"> chứa cả dòng.
    # -------------------------------------------------------------
    # Dùng cách viết tắt (/..) cho nhanh gọn:
    dong_cua_B = page.locator("//span[text()='Trần Văn B']/..")
    
    print("Thông tin dòng: ", dong_cua_B.text_content())


    # -------------------------------------------------------------
    # 3. TUYỆT CHIÊU KẾT HỢP CONTAINS
    # BÀI TOÁN: Tìm nút xóa có class chứa chữ "delete" (Phòng trường hợp class bị đổi)
    # -------------------------------------------------------------
    nut_xoa_B = page.locator("//span[text()='Trần Văn B']/following-sibling::button[contains(@class, 'delete')]")
    nut_xoa_B.click()

    print("✅ Đã thi triển thành công bí kíp Gia phả XPath!")

(Lưu ý của Playwright: Nếu chuỗi của bạn bắt đầu bằng // hoặc .., Playwright sẽ tự động hiểu đó là XPath mà không cần bạn phải khai báo dài dòng).


🧩 VI. ĐÚC KẾT & BÀI TẬP VỀ NHÀ

Teacher

Teacher

Hà Lan

QA Automation

With over 5 years of experience in web, API, and mobile test automation, built strong expertise in designing and maintaining automation frameworks across various domains and international projects. Committed to mentoring and knowledge sharing, I provide practical guidance and proven techniques to help aspiring testers develop their skills and succeed in the automation field.

Cộng đồng Automation Testing Việt Nam:

🌱 Telegram Automation Testing:   Cộng đồng Automation Testing
🌱 
Facebook Group Automation: Cộng đồng Automation Testing Việt Nam
🌱 
Facebook Fanpage: Cộng đồng Automation Testing Việt Nam - Selenium
🌱 Telegram
Manual Testing:   Cộng đồng Manual Testing
🌱 
Facebook Group Manual: Cộng đồng Manual Testing Việt Nam

Chia sẻ khóa học lên trang

Bạn có thể đăng khóa học của chính bạn lên trang Anh Tester để kiếm tiền

Danh sách bài học