NỘI DUNG BÀI HỌC

  • 🛠️ Hướng dẫn cài đặt môi trường

  • 🚀 Khởi tạo dự án Playwright

  • 📊 Chạy test và xem báo cáo

  • 🔬 Phân tích sâu về page object



🔧 Phần 1: Chuẩn bị môi trường (Prerequisites)


Trước khi bắt đầu với Playwright, máy tính của các bạn cần được cài đặt một vài công cụ thiết yếu.


Cài đặt Node.js và npm 📦

Playwright được xây dựng trên nền tảng Node.js, do đó chúng ta cần cài đặt nó trước tiên. npm (Node Package Manager) sẽ được cài đặt tự động cùng với Node.js, đây là công cụ để quản lý các thư viện mà dự án của chúng ta sẽ sử dụng.

✅ Cách kiểm tra: Mở terminal (hoặc Command Prompt/PowerShell trên Windows) và chạy các lệnh sau:

Bash

node -v

npm -v

Nếu bạn thấy phiên bản hiện ra, có nghĩa là bạn đã cài đặt thành công.

📥 Cách cài đặt: Nếu chưa có, hãy truy cập trang chủ của Node.js tại https://nodejs.org/ và tải về phiên bản LTS (Long Term Support) được khuyến nghị cho hầu hết người dùng.


Cài đặt Visual Studio Code (Khuyến nghị) 👨‍💻

Đây là một trình soạn thảo mã nguồn (code editor) miễn phí, mạnh mẽ và phổ biến nhất hiện nay, được phát triển bởi Microsoft. VS Code hỗ trợ rất tốt cho TypeScript và có nhiều tiện ích mở rộng (extensions) giúp cho việc lập trình với Playwright trở nên dễ dàng hơn.

📥 Tải về tại: https://code.visualstudio.com/

 

✨ Khởi tạo dự án Playwright TS

Bây giờ chúng ta sẽ sử dụng chính công cụ dòng lệnh của Playwright để khởi tạo một dự án mới. Đây là cách nhanh nhất và chuẩn nhất.

📂 Bước 1: Tạo một thư mục mới cho dự án

Hãy tạo một thư mục trống ở nơi bạn muốn lưu trữ dự án của mình. Mở terminal và di chuyển vào thư mục đó.
# Tạo một thư mục mới tên la "playwright-ts-demo"
mkdir playwright-ts-demo

# Di chuyển vào thư mục vừa tạo

cd playwright-ts-demo

⚡ Bước 2: Chạy lệnh khởi tạo Playwright

Tại thư mục dự án, hãy chạy lệnh sau. Lệnh này sẽ khởi tạo một trình hướng dẫn cài đặt tự động.

 

npm init playwright@latest


🤖 Bước 3: Tương tác với trình hướng dẫn cài đặt

Sau khi chạy lệnh trên, Playwright sẽ hỏi bạn một vài câu hỏi để cấu hình dự án.

Do you want to use TypeScript or JavaScript? (Bạn muốn dùng TypeScript hay JavaScript?)

Hãy chọn TypeScript. Dùng các phím mũi tên và nhấn Enter.

Where to put your end-to-end tests? (Nơi đặt các file test?)

Mặc định là tests. Đây là một lựa chọn tốt, hãy nhấn Enter để chấp nhận.

Add a GitHub Actions workflow? (Thêm một quy trình GitHub Actions?)

Đây là tính năng để chạy test tự động trên GitHub. Hiện tại chúng ta chưa cần, hãy chọn false (hoặc n).

Install Playwright browsers? (Cài đặt các trình duyệt của Playwright?)

Hãy chọn true (hoặc y). Lệnh này sẽ tải về các phiên bản trình duyệt đã được vá lỗi đặc biệt cho Playwright (Chromium, Firefox, WebKit), đảm bảo tính ổn định khi chạy test.

Sau khi trả lời xong, trình cài đặt sẽ tự động tải về các gói cần thiết. Quá trình này có thể mất vài phút tùy thuộc vào tốc độ mạng của bạn.


🎉 Kết quả:

Khi hoàn tất, bạn sẽ thấy một thông báo thành công và cấu trúc thư mục dự án của bạn sẽ trông như sau:

playwright-ts-demo/

├── node_modules/       # Thư mục chứa các thư viện đã cài đặt

├── tests/              # Thư mục chứa các file test

│   └── example.spec.ts # Một file test mẫu

├── .gitignore          # Các file/thư mục được bỏ qua bởi Git

├── package.json        # File cấu hình dự án Node.js

├── package-lock.json   # File khóa phiên bản các thư viện

└── playwright.config.ts# File cấu hình chính của Playwright

🔬  Khám phá dự án và Chạy thử kịch bản đầu tiên

Bây giờ, hãy mở thư mục dự án playwright-ts-demo bằng Visual Studio Code.


Khám phá file test mẫu example.spec.ts 📄

Mở file tests/example.spec.ts. Bạn sẽ thấy một đoạn code mẫu được viết bằng TypeScript.

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


test('has title', async ({ page }) => {

  await page.goto('https://playwright.dev/');

  // Expect a title "to contain" a substring.

  await expect(page).toHaveTitle(/Playwright/);

});


test('get started link', async ({ page }) => {

  await page.goto('https://playwright.dev/');

  // Click the get started link.

  await page.getByRole('link', { name: 'Get started' }).click();

  // Expects page to have a heading with the name of Installation.

  await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();

});

Đoạn mã này định nghĩa 2 kịch bản test:

'has title': Mở trang chủ của Playwright và kiểm tra xem tiêu đề trang có chứa chữ "Playwright" hay không.

'get started link': Mở trang chủ, tìm và click vào link có chữ "Get started", sau đó kiểm tra xem trang mới có hiển thị tiêu đề "Installation" hay không.

Chạy kịch bản test ▶️

Playwright cung cấp cho chúng ta một câu lệnh đơn giản để chạy tất cả các file test trong dự án. Mở terminal ngay trong VS Code (bằng cách vào Terminal > New Terminal) và chạy lệnh sau:

npx playwright test

Lệnh này sẽ chạy các kịch bản test trên tất cả các trình duyệt được cấu hình (mặc định là Chromium, Firefox, và WebKit) ở chế độ headless (không hiển thị giao diện người dùng).


Xem báo cáo kết quả 📊

Sau khi chạy xong, bạn sẽ thấy kết quả trong terminal. Để xem một báo cáo trực quan và chi tiết hơn, hãy chạy lệnh sau:

npx playwright show-report

Lệnh này sẽ mở một trang web báo cáo trong trình duyệt của bạn, nơi bạn có thể xem chi tiết kết quả của từng bước trong mỗi kịch bản test, bao gồm cả ảnh chụp màn hình và video (nếu được cấu hình).


Phần 2: Tìm hiểu về page là gì?

Bạn có để ý không, mọi câu lệnh, mọi tương tác của chúng ta đều bắt đầu từ một đối tượng có tên là page.

await page.goto(...)

await page.getByRole(...)

await expect(page).toHaveTitle(...)

Vậy page thực sự là gì? 🤔 Tại sao nó lại quyền năng và có mặt ở khắp mọi nơi? Trong bài viết này, chúng ta sẽ khám phá chi tiết về page - đối tượng được mệnh danh là "linh hồn" 👻 của Playwright.

❓ page là gì? Giải mã khái niệm cốt lõi

Một cách đơn giản nhất, một đối tượng page đại diện cho một tab (thẻ) duy nhất 📑 trong trình duyệt.

Hãy tưởng tượng bạn mở trình duyệt Chrome lên. Mỗi tab bạn mở ra (Trang chủ, YouTube, Facebook...) là một môi trường độc lập. Mỗi tab có URL riêng, lịch sử duyệt web riêng (tiến/lùi), có DOM (cấu trúc HTML) riêng. Đối tượng page trong Playwright chính là một công cụ lập trình cho phép bạn điều khiển và tương tác với tất cả mọi thứ bên trong một tab như vậy.

Vòng đời của page 🔄

Trong một kịch bản test của Playwright, bạn không cần phải tự tạo ra page. Test runner của Playwright sẽ làm điều đó cho bạn:

🌱 Khởi tạo: Trước mỗi test case, Playwright sẽ tự động tạo ra một BrowserContext (giống như một profile trình duyệt riêng biệt, sạch sẽ) và sau đó mở một page (một tab mới) hoàn toàn trống trong context đó.

⚙️ Sử dụng: page được truyền vào test case của bạn thông qua cú pháp test(async ({ page }) => { ... }). Toàn bộ test case của bạn sẽ diễn ra trong tab duy nhất này.

🗑️ Hủy bỏ: Sau khi test case kết thúc (dù thành công hay thất bại), page và BrowserContext tương ứng sẽ bị hủy bỏ hoàn toàn.

Điều này đảm bảo một nguyên tắc vàng trong kiểm thử: Sự cô lập (Isolation) 🛡️. Mỗi test case được chạy trên một "tờ giấy trắng", không bị ảnh hưởng bởi các test case trước đó.

🦸 Các "Siêu Năng Lực" của page

page là cánh cổng để bạn thực thi mọi mệnh lệnh. Dưới đây là những nhóm khả năng chính của nó.


Điều Hướng (Navigation) - Người Dẫn Đường 🧭

Đây là nhóm hành động cơ bản nhất, cho phép bạn di chuyển qua lại giữa các trang web.

await page.goto(url): Đi đến một địa chỉ web. Đây gần như luôn là lệnh đầu tiên trong mọi test case.

await page.goBack(): Quay lại trang trước đó (tương đương nút Back).

await page.goForward(): Đi tới trang kế tiếp (tương đương nút Forward).

await page.reload(): Tải lại trang hiện tại (tương đương nút Reload hoặc F5).


Tương Tác Với Phần Tử (Interaction) - Đôi Mắt 👀 và Đôi Tay ✋

Đây là năng lực cốt lõi. page cung cấp các phương thức để "nhìn" (tìm kiếm) và "chạm" (tương tác) vào các phần tử trên trang.

page.getByRole(), page.getByText(), page.getByLabel(), page.locator()...: Đây là "đôi mắt" của page. Chúng không tìm kiếm ngay lập tức mà tạo ra các đối tượng Locator (công thức tìm kiếm).

Sau khi có locator, bạn có thể dùng "đôi tay" để tương tác: .click(), .fill(), .check(), .press(), .hover()...

Ví dụ một chuỗi tương tác hoàn chỉnh:

test('should login to the system', async ({ page }) => {

  // 1. Điều hướng

  await page.goto('https://example.com/login');

  // 2. Dùng "mắt" để tìm và "tay" để điền

  await page.getByLabel('Username').fill('myuser');

  await page.getByLabel('Password').fill('mypassword');

  // 3. Dùng "mắt" để tìm và "tay" để click

  await page.getByRole('button', { name: 'Sign In' }).click();

});

 

Truy Vấn & Khẳng Định (Querying & Assertion) - Bộ Não Phân Tích 🧠

page không chỉ hành động, nó còn có thể "đọc" và "hiểu" trạng thái của trang web.

page.url(): Lấy chuỗi URL hiện tại của trang.

page.title(): Lấy tiêu đề của trang (thẻ <title>).

page.content(): Lấy toàn bộ nội dung HTML của trang.

Kết hợp với expect: await expect(page).toHaveURL(...), await expect(page).toHaveTitle(...).


Xử Lý Môi Trường Trang (Environment Handling) - Người Kiểm Soát Toàn Năng 🎛️

Đây là những năng lực nâng cao, cho phép bạn vượt ra ngoài các tương tác người dùng thông thường.

💬 Xử lý Dialogs: Bắt và xử lý các hộp thoại alert, confirm, prompt.

page.on('dialog', async dialog => {

  console.log(dialog.message()); // In ra nội dung của alert

  await dialog.accept(); // Nhấn OK

});


📡 Giả lập Mạng (Network Mocking):
Đây là một "siêu năng lực" cực kỳ mạnh. Bạn có thể chặn các request mạng, thay đổi response trả về, hoặc làm cho request bị lỗi. Điều này giúp test case của bạn chạy nhanh hơn và không phụ thuộc vào backend.

// Chặn tất cả các file ảnh không cho tải về

await page.route('**/*.{png,jpg,jpeg}', route => route.abort());


// Giả lập API trả về dữ liệu giả

await page.route('**/api/user', async route => {

  await route.fulfill({ json: { id: 1, name: 'Gemini' } });

});


📜 Thực thi mã JavaScript:
Chạy các đoạn mã JavaScript tùy ý trong bối cảnh của trình duyệt.

// Lấy giá trị từ localStorage

const theme = await page.evaluate(() => localStorage.getItem('theme'));

📸 Chụp ảnh & 🎥 Quay video:

page.screenshot({ path: 'screenshot.png' }): Chụp lại màn hình trang web.

Playwright Test Runner còn tự động quay video lại toàn bộ quá trình chạy test, rất hữu ích khi debug lỗi.

🏗️  page trong Bức Tranh Toàn Cảnh

Để hiểu rõ hơn về page, hãy đặt nó vào kiến trúc tổng thể của Playwright:

BrowserType: Lõi của trình duyệt (chromium, firefox, webkit).

Browser: Một instance của trình duyệt đang chạy (một cửa sổ trình duyệt).

BrowserContext: Một môi trường độc lập bên trong Browser. Nó quản lý session, cookies, localStorage. Mỗi context giống như một profile người dùng riêng biệt (ví dụ: cửa sổ ẩn danh).

Page: Một tab duy nhất bên trong BrowserContext. Một BrowserContext có thể có nhiều page.

Khi bạn chạy test(async ({ page }) => ...) , Playwright Test Runner đã âm thầm thực hiện tất cả các bước trên để trao cho bạn một đối tượng page mới tinh, sẵn sàng để sử dụng.

Phần 3: Giải thích thêm về Fixtures và Cú pháp ({ page })

Khi Playwright Test Runner chuẩn bị chạy một test case, nó không chỉ tạo ra một đối tượng page. Nó tạo ra một "hộp dụng cụ" 🧰 chứa RẤT NHIỀU thứ hữu ích. Hộp dụng cụ này là một đối tượng lớn, và mỗi món đồ trong đó được gọi là một Fixture.

Hãy hình dung đối tượng mà Playwright ngầm tạo ra trông như thế này:

const toolboxObject = {

  page: aPageObject,         // "Linh hồn" - tab trình duyệt

  context: aBrowserContext,  // Ngữ cảnh trình duyệt (chứa page, cookie, storage)

  browser: aBrowserInstance,   // Bản thân trình duyệt (Chrome, Firefox)

  browserName: 'chromium',     // Tên trình duyệt đang chạy

  request: anAPIRequestContext, // Công cụ để gửi request API

  // ... và nhiều fixtures khác

};


Hàm test của bạn async () => {} sẽ được Playwright gọi và truyền cho nó nguyên cả cái toolboxObject này làm tham số ĐẦU TIÊN.

Vậy, cú pháp test(async ({ page }) => { ... }) chính là sự kết hợp của hai điều trên:

Nó đang sử dụng Object Destructuring để nói với Playwright rằng:

"Từ cái 'hộp dụng cụ' (toolbox object) to lớn mà anh cung cấp, tôi chỉ cần dùng món đồ có tên là page thôi. Hãy lấy nó ra giúp tôi."

Bạn hoàn toàn có thể lấy nhiều fixtures cùng lúc. Nếu bạn cần cả page và tên của trình duyệt đang chạy, bạn chỉ cần yêu cầu thêm:

 

test('should work on different browsers', async ({ page, browserName }) => {

  await page.goto('https://playwright.dev');

  if (browserName === 'firefox') {

    console.log('Running on Firefox, doing something special...');

    // Thêm logic riêng cho Firefox

  } else {

    console.log('Running on a different browser.');

  }

});

Nếu bạn chỉ cần test API và không cần đến trình duyệt, bạn có thể chỉ yêu cầu request:

test('API should return user data', async ({ request }) => {

  const response = await request.get('/api/users/1');

  expect(response.ok()).toBe(true);

});

** Tại sao thiết kế này lại hay? (Lợi ích)**💡

Cách tiếp cận dùng Fixtures và Destructuring này mang lại rất nhiều lợi ích:

🔎 Rõ ràng và tường minh (Explicitness): Nhìn vào dòng đầu tiên test(async ({ page, request }) => ...) là bạn biết ngay lập tức test case này cần những "dụng cụ" gì để hoạt động. Nó tự mô tả (self-documenting).

🧩 Linh hoạt và dễ mở rộng (Extensibility): Playwright có thể thêm các fixtures mới mà không làm ảnh hưởng test cũ. Quan trọng hơn, bạn có thể tự tạo fixtures của riêng mình. Ví dụ, tạo fixture loggedInPage tự động đăng nhập. Khi đó bạn chỉ cần viết: test(async ({ loggedInPage }) => { ... }).

⚡ Hiệu quả (Efficiency): Playwright rất thông minh. Nó sẽ chỉ khởi tạo những fixtures mà bạn thực sự yêu cầu. Trong ví dụ test API ở trên, vì bạn không yêu cầu page, Playwright sẽ không tốn tài nguyên để khởi động cả một trình duyệt.

✨ Sạch sẽ (Cleanliness): Nó tránh việc phải truyền vào một loạt các tham số theo đúng thứ tự (test(page, context, request, ...)), vốn rất dễ gây lỗi và khó đọc.

 

 

Teacher

Teacher

Nguyên Hoàng

Automation Engineer

With 7+ years of hands-on experience across multiple languages and frameworks. I'm here to share knowledge, helping you turn complex processes into simple and effective solutions.

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