NỘI DUNG BÀI HỌC

✅ Hiểu được mối liên kết giữa các tầng trong POM (BasePage → Page Object → Test Layer).
✅ Nắm vững cấu trúc dự án hoàn chỉnh và ý nghĩa từng thư mục trong automation framework.
✅ Phân biệt và áp dụng được các mô-đun mở rộng trong POM: Component, Utils, Data, Config.
✅ Biết cách xây dựng dòng chảy nghiệp vụ (Business Flow) giữa các Page Object.
✅ Định hình được tư duy thiết kế framework chuyên nghiệp có khả năng mở rộng và tái sử dụng.



I. ÔN TẬP NGẮN: TRIẾT LÝ CỐT LÕI CỦA POM

1. POM là gì?

Page Object Model là mô hình giúp tách biệt:

  • WHAT – Nghiệp vụ cần kiểm thử.

  • HOW – Cách thực hiện thao tác trên UI.

2. Mục tiêu chính

  • Tập trung logic kỹ thuật vào BasePage.

  • Mô tả nghiệp vụ rõ ràng trong Page Object.

  • Giúp test case ngắn gọn, dễ đọc, dễ mở rộng.


II. TỔNG QUAN VỀ CẤU TRÚC POM NÂNG CAO

Một framework chuyên nghiệp thường mở rộng từ kiến trúc POM cơ bản sang mô hình đa tầng sau:

project_root/
│
├── pages/                               ← PAGE OBJECT LAYER (Nghiệp vụ & Nền tảng)
│   ├── base_page.py                     → Base class cho tất cả Page Object
│   └── login_page.py                    → Chứa locators + các action của trang Login
│
├── components/                          ← (Optional) COMPONENT LAYER
│   └── header_component.py              → Component UI tái sử dụng đơn giản
│
├── resources/                           ← (Optional) DATA & CONFIG LAYER
│   └── config.json                      → File cấu hình hoặc test data đơn giản
│
├── utils/                               ← (Optional) HELPER LAYER
│   └── helper.py                        → Các hàm hỗ trợ phi UI (vd: log, đọc file)
│
├── tests/                               ← TEST SCENARIO LAYER (WHAT)
│   └── test_login_pom.py                → Chứa các test case cho luồng đăng nhập
│
├── conftest.py                          ← THE GLUE (CONNECTOR)
│                                         → Setup/Teardown và quản lý fixture
│
├── reports/                             ← OUTPUT LAYER (Kết quả kiểm thử)
│   └── report.html                      → File báo cáo kết quả test đơn giản
│
└── screenshots/                         ← EVIDENCE LAYER (Ảnh minh chứng)
    └── screenshot.png                   → File ảnh chụp màn hình khi test lỗi

 

III. BASEPAGE NÂNG CAO – CHUẨN HÓA & MỞ RỘNG HÀNH ĐỘNG

1. Định nghĩa

BasePage giờ đây nằm trực tiếp trong thư mục pages/. Đây là lớp nền tảng duy nhất mà login_page.py (và các page sau này) kế thừa. Lớp này xử lý:

  • Wait động (Explicit Wait).

  • Logging.

  • Screenshot on Fail.


2. Ví dụ – pages/base_page.py

from playwright.sync_api import Page, expect, TimeoutError

class BasePage:
    """Lớp cha mở rộng với Wait, Logging, Screenshot và các hành động tái sử dụng."""

    def __init__(self, page: Page):
        self.page = page

    def _visit(self, url: str):
        """Điều hướng trang web."""
        print(f"[NAVIGATE] {url}")
        self.page.goto(url, wait_until="domcontentloaded")

    def _click(self, locator: str, name: str = ""):
        """Click vào element có chờ sẵn sàng."""
        try:
            element = self.page.locator(locator)
            element.wait_for(state="visible", timeout=5000)
            print(f"[CLICK] {name or locator}")
            element.click()
        except TimeoutError:
            print(f"[ERROR] Element {locator} không hiển thị.")
            self._take_screenshot(f"error_click_{name}.png")
            raise

    def _fill(self, locator: str, text: str, name: str = ""):
        """Điền dữ liệu vào ô input."""
        print(f"[FILL] {name or locator}: {text}")
        self.page.locator(locator).fill(text)

    def _assert_visible(self, locator: str, name: str = ""):
        """Kiểm tra element hiển thị."""
        expect(self.page.locator(locator)).to_be_visible()
        print(f"[ASSERT] {name or locator} hiển thị thành công.")

    def _take_screenshot(self, filename: str):
        """Lưu ảnh chụp màn hình (sử dụng khi test fail)."""
        path = f"screenshots/{filename}"
        self.page.screenshot(path=path)
        print(f"[SCREENSHOT] Lưu tại: {path}")
 

IV. COMPONENT OBJECT – TÁCH NHỮNG PHẦN TỬ UI DÙNG CHUNG

1. Khái niệm Ngay cả trong dự án tối giản, ta vẫn nên dùng Component cho các phần tử xuất hiện xuyên suốt (như Header sau khi đăng nhập thành công). Nó kế thừa trực tiếp từ BasePage.

2. Ví dụ – components/header_component.py

from pages.base_page import BasePage

class HeaderComponent(BasePage):
    """Đại diện cho thanh header sau khi login."""

    MENU_BUTTON = "#react-burger-menu-btn"
    LOGOUT_LINK = "#logout_sidebar_link"

    def logout(self):
        """Mở menu và đăng xuất."""
        self._click(self.MENU_BUTTON, "Menu Button")
        self._click(self.LOGOUT_LINK, "Logout Link")

 

V. DATA-DRIVEN TESTING (DDT) CƠ BẢN

Thay vì tạo thư mục data/ riêng biệt, ta gộp vào resources/ để giữ đúng tính tối giản (1 file dùng chung cho config và data).

1. Ví dụ cấu trúc file – resources/config.json

{
  "valid_user": {
    "username": "standard_user",
    "password": "secret_sauce"
  },
  "locked_user": {
    "username": "locked_out_user",
    "password": "secret_sauce"
  }
}

2. Cách sử dụng trong test – tests/test_login_pom.py

import json
from pages.login_page import LoginPage

def test_login_from_json(page):
    login_page = LoginPage(page)
    
    # Đọc data từ thư mục resources
    with open("resources/config.json") as f:
        data = json.load(f)

    valid = data["valid_user"]
    login_page.login(valid["username"], valid["password"])
    login_page.assert_login_successful()

VI. PAGE OBJECT MỞ RỘNG – CHUỖI HÀNH ĐỘNG NGHIỆP VỤ

Trong cấu trúc tinh gọn này, chúng ta mô phỏng luồng: Login thành công → Đăng xuất qua Header Component.

from pages.login_page import LoginPage
from components.header_component import HeaderComponent

def test_login_and_logout_flow(page):
    # 1. Login
    login_page = LoginPage(page)
    login_page.visit_login_page()
    login_page.login("standard_user", "secret_sauce")
    login_page.assert_login_successful()

    # 2. Logout (Sử dụng component chung thay vì viết vào page)
    header = HeaderComponent(page)
    header.logout()
    
    # 3. Verify quay về trang login
    login_page.assert_at_login_page()

 

Ưu điểm của chuỗi này:

  • Mỗi trang có trách nhiệm riêng.

  • Không cần lặp lại logic login hay add to cart ở nhiều test khác.

  • Test mô tả hành trình người dùng thực tế bằng ngôn ngữ nghiệp vụ.


Sơ đồ 1 chiều

tests/ (WHAT)
   ↓  (gọi nghiệp vụ)
pages/ (Page Objects – HOW nghiệp vụ theo trang)
   ↓  (tái sử dụng)
components/ (UI dùng chung theo thành phần)
   ↓  (kế thừa/ủy quyền)
core/ (Base classes: BasePage, BaseComponent – HOW kỹ thuật)
   ↓  (thao tác thật)
Playwright API (page, locator, expect)

resources/ (config, testdata) → được đọc bởi tests/ hoặc pages/ (khi cần)
utils/ (db, api, file, logger) → được gọi bởi tests/ hoặc pages/ (khi cần)
conftest.py (fixtures) → khởi tạo “đối tượng + dữ liệu” và bơm vào tests/
reports/, screenshots/ → nhận log, ảnh, kết quả assert khi chạy


VIII. TỔNG KẾT KIẾN THỨC POM NÂNG CAO

Khái niệm Định nghĩa Ứng dụng trong automation
BasePage nâng cao Lớp cha chuẩn hóa hành động với Wait, Logging, Screenshot Giúp test ổn định, dễ debug
Component Object Mô hình tách phần tử UI dùng chung (header, sidebar, popup) Tăng tái sử dụng, giảm lặp code
Data-Driven Testing Cách tách dữ liệu test ra khỏi logic test Dễ mở rộng, dễ quản lý test data
Business Flow Chuỗi hành động kết hợp nhiều Page Object Mô phỏng luồng người dùng thực tế
Clean Test Case Test chỉ thể hiện luồng nghiệp vụ, không chứa kỹ thuật Dễ đọc, dễ bảo trì, rõ ràng với non-dev


IX. BÀI TẬP THỰC HÀNH

Trang web: https://hrm.anhtester.com/erp/login

Yêu cầu:

📦 PlaywrightProject/
│
├── Core/                                  # Thư mục chứa lớp nền (BasePage) dùng chung
│   ├── base_page.py                       # Định nghĩa các hàm cơ bản: open_url, click, fill, screenshot
│   └── __init__.py                        # Giúp Python nhận diện đây là package
│
├── components/                            # Thư mục chứa các thành phần UI tái sử dụng (Header, Footer)
│   ├── header_component.py                # Xử lý menu header: click từng mục, chụp ảnh, logout
│   └── __init__.py
│
├── pages/                                 # Thư mục chứa các Page Object đại diện cho từng trang
│   ├── login_page.py                      # Trang đăng nhập: đọc dữ liệu từ JSON, login, chụp ảnh, logout
│   └── __init__.py
│
├── data/                                  # Lưu trữ dữ liệu test (JSON, CSV, Excel)
│   ├── credentials.json                   # Chứa thông tin đăng nhập test
│   └── __init__.py
│
├── results/                               # Lưu kết quả chạy test (report HTML)
│   ├── report.html                        # Báo cáo tự động sinh sau khi chạy pytest
│   └── __init__.py
│
├── screenshots/                           # Thư mục lưu toàn bộ ảnh chụp màn hình khi test
│   └── (ảnh tự sinh khi chạy test)
│
├── tests/                                 # Chứa file test case thực tế (Pytest)
│   ├── test_login_flow.py                 # Kịch bản: mở → đăng nhập → chụp ảnh → logout
    └── __init__.py

​

Đánh giá hoàn thành:

Tiêu chí Mức độ đạt yêu cầu
Có Component Header riêng
Dữ liệu test tách riêng file JSON
Flow liên kết nhiều Page Object
Không chứa locator trong test
Test chạy ổn định, dễ đọc

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