NỘI DUNG BÀI HỌC

Làm chủ kỹ thuật Debug: Biết cách dùng Inspector để "chạy từng bước" và Trace Viewer để "xem lại lịch sử" khi test case thất bại.

Tối ưu thời gian (Parallel Execution): Biết cách chạy song song nhiều test case cùng lúc để giảm thời gian chờ đợi từ hàng tiếng xuống hàng phút.

Kiểm thử đa trình duyệt: Chạy bộ test trên cả 3 engine phổ biến (Chromium, Firefox, WebKit) chỉ với một dòng lệnh.



🧠 I. Debugging

1. Khái niệm: Tại sao và Khi nào cần Debug?

Khái niệm

Debug là quá trình xác định, phân tích và loại bỏ các lỗi (bug) trong phần mềm. Mục tiêu là đảm bảo chương trình chạy đúng logic và đạt hiệu suất tối ưu.

Tại sao cần Debug?

  • Hiểu sâu mã nguồn: Khi debug từng bước, bạn thấy được luồng dữ liệu biến đổi như thế nào qua từng dòng lệnh.

  • Tiết kiệm thời gian: Sửa lỗi sớm giúp tránh các hệ lụy nghiêm trọng khi phần mềm đã triển khai thực tế.

  • Nâng cao chất lượng: Đảm bảo phần mềm không bị crash hoặc cho ra kết quả sai lệch.

Khi nào cần Debug?

  • Lỗi logic (Logic Error): Code chạy không lỗi nhưng kết quả đầu ra sai.

  • Lỗi runtime (Runtime Error): Chương trình bị dừng đột ngột khi đang chạy (ví dụ: chia cho 0, gọi biến null).

  • Hiệu suất kém: Khi ứng dụng chạy chậm hoặc tốn quá nhiều bộ nhớ (Memory Leak).


2. Các kiểu Debug phổ biến

Dưới đây là 5 kiểu debug thường dùng nhất trong giới lập trình:

  1. Print Debugging (Logging): Thêm các câu lệnh như console.log() hoặc printf() để in giá trị biến ra màn hình.

  2. Interactive Debugging: Sử dụng các công cụ chuyên dụng (Debugger) để dừng chương trình tại một điểm, xem trạng thái bộ nhớ và biến.

  3. Remote Debugging: Debug một ứng dụng đang chạy trên một máy chủ khác hoặc thiết bị khác từ xa.

  4. Static Analysis (Phân tích tĩnh): Kiểm tra lỗi cú pháp và logic tiềm ẩn mà không cần chạy code (sử dụng Linters như ESLint, Pylint).

  5. Post-mortem Debugging: Phân tích dữ liệu lỗi (log/dump file) sau khi chương trình đã bị sập để tìm nguyên nhân.


3. Cách Debug bằng công cụ trên VS Code

VS Code tích hợp bộ debugger mạnh mẽ giúp bạn không cần in log thủ công.

Các thành phần chính

  • Breakpoints (Điểm dừng): Nhấp chuột trái vào lề trái số dòng để đặt dấu chấm đỏ. Chương trình sẽ dừng lại tại đây.

  • Variables: Xem giá trị hiện tại của tất cả các biến đang có.

  • Watch: Theo dõi sự thay đổi của một biến hoặc biểu thức cụ thể.

  • Call Stack: Xem thứ tự các hàm đã được gọi để dẫn đến dòng hiện tại.

Các bước thực hiện

  1. Mở file code: Nhấn F5 hoặc chọn biểu tượng Run and Debug ở thanh bên trái.

  2. Cấu hình (nếu cần): Chọn môi trường (Node.js, Python, C++,...) để VS Code tạo file launch.json.

  3. Đặt Breakpoint: Click vào dòng bạn nghi ngờ có lỗi.

  4. Điều khiển bằng thanh công cụ:

    • Continue (F5): Chạy tiếp đến điểm dừng tiếp theo.

    • Step Over (F10): Chạy qua dòng hiện tại (không nhảy vào trong hàm).

    • Step Into (F11): Nhảy vào bên trong hàm của dòng hiện tại.

    • Step Out (Shift + F11): Thoát ra khỏi hàm hiện tại.


4. Những cách Debug trên VS Code

4.1. Sử dụng Playwright Extension (Cách khuyến nghị)

Đây là cách trực quan và mạnh mẽ nhất. Microsoft cung cấp extension chính thức để tích hợp Playwright vào VS Code.

  • Cài đặt: Tìm và cài đặt extension "Playwright Test for VS Code".

  • Cách dùng:

    1. Mở file test Python (thường dùng với pytest).

    2. Một biểu tượng hình tam giác xanh (Play) sẽ xuất hiện bên cạnh mỗi hàm test.

    3. Chuột phải vào biểu tượng đó và chọn Debug Test.

  • Ưu điểm: Tự động kết hợp với trình gỡ lỗi của VS Code, cho phép đặt Breakpoint (điểm dừng) tại các dòng lệnh page.goto() hoặc page.click().


4.2. Debug bằng Playwright Inspector (PWDEBUG)

Playwright có một công cụ đi kèm cực kỳ mạnh mẽ gọi là Inspector. Nó cho phép bạn "bước" qua từng dòng code và thấy trình duyệt thực thi tương ứng.

  • Câu lệnh terminal:

    # Windows
    set PWDEBUG=1
    pytest test_file.py
    
    # macOS/Linux
    PWDEBUG=1 pytest test_file.py
    
    
  • Tính năng: * Mở một cửa sổ riêng biệt để kiểm soát trình duyệt.

    • Tự động bôi đậm (highlight) các phần tử (element) mà code đang tương tác.

    • Hỗ trợ tạo (pick) selector cực nhanh.


4.3. Sử dụng lệnh page.pause()

Nếu bạn muốn dừng chương trình tại một điểm nhất định để kiểm tra trạng thái trang web mà không muốn đặt breakpoint phức tạp, hãy dùng page.pause().

  • Code:

    def test_example(page):
        page.goto("https://example.com")
        # Chương trình sẽ dừng lại ở đây và mở Inspector
        page.pause() 
        page.click("#submit")

     

  • Lưu ý: Khi chạy lệnh này, trình duyệt sẽ tự động chuyển sang chế độ Headful (có giao diện) để bạn quan sát.


4.4. Sử dụng Playwright Trace Viewer

Trace Viewer không phải là debug thời gian thực (real-time), nhưng nó là "vũ khí" tối thượng khi test bị fail trên server (CI/CD) hoặc khi bạn không rảnh để ngồi canh màn hình.

  • Cách ghi log:

    Chạy lệnh test với cờ trace:

    pytest --tracing on​
  • Cách xem: Sau khi chạy xong, Playwright tạo ra một file .zip. Bạn mở nó bằng lệnh:

    playwright show-trace trace.zip
  • Thông tin nhận được: Hình ảnh chụp màn hình từng bước, log mạng (network), console log và mã nguồn chính xác tại thời điểm lỗi.


4.5. Chế độ Headful và Slow Mo (Chạy chậm)

Đôi khi code chạy quá nhanh khiến bạn không kịp nhìn thấy lỗi. Bạn có thể làm chậm quá trình này lại.

  • Cấu hình trong code:

    # Chạy có giao diện và chậm lại 500ms mỗi thao tác
    browser = playwright.chromium.launch(headless=False, slow_mo=500)
  • Lợi ích: Giúp mắt người kịp theo dõi luồng tương tác, từ đó phát hiện các vấn đề về hiển thị hoặc timing (chờ phần tử chưa xuất hiện).


Bảng so sánh các phương pháp

Phương pháp Khi nào nên dùng? Mức độ chi tiết
VS Code Debugger Khi lỗi logic trong code Python Rất cao
Playwright Inspector Khi lỗi tìm không thấy Element (Selector) Cao
page.pause() Dừng nhanh để can thiệp thủ công vào trình duyệt Trung bình
Trace Viewer Khi test fail trên môi trường Jenkins/GitHub Actions Tuyệt đối (xem lại quá khứ)

 

🧠 II. Chạy song song (Parallel Execution) ⚡

1. Khái niệm

Test Song song (Parallel Testing) là kỹ thuật chạy nhiều test case chức năng độc lập cùng một lúc để giảm tổng thời gian kiểm thử.

  • Mục đích chính: Tối ưu tốc độ thực thi, tăng tốc độ phản hồi (feedback) của quy trình CI/CD.

  • Công cụ thường dùng: Pytest, JUnit, TestNG (thường kết hợp với Playwright, Selenium).

  • Số lượng: Thường là 4-8 luồng (thread) hoặc quá trình (process) chạy song song trên một máy tính cá nhân hoặc server CI.

2. Dùng cho những Test Case nào?

Test song song chỉ áp dụng cho các test case độc lập và không chia sẻ trạng thái (State).

Tiêu chí Mô tả Ví dụ phù hợp (Dùng Playwright)
Độc lập (Independent) Kết quả của Test A không ảnh hưởng đến Test B. Test đăng nhập và Test tìm kiếm
Đồng nhất (Homogeneous) Các test đang kiểm tra cùng một môi trường hoặc phiên bản code. Kiểm tra quy trình đặt hàng trên trình duyệt Chrome và Firefox cùng lúc.
Không xung đột (Non-Conflicting Data) Mỗi luồng sử dụng dữ liệu test riêng biệt, không đụng độ với luồng khác. Mỗi luồng đăng nhập bằng một tài khoản người dùng duy nhất.

 

Ví dụ Về Test Case Phù Hợp:

  • Đăng nhập (User A) và đăng xuất (User B).

  • Tìm kiếm (User A) và thêm sản phẩm vào giỏ hàng (User B).

  • Kiểm tra giao diện trang chủ (User A) và trang danh mục (User B).


3. Cài đặt thư viện hỗ trợ

Bạn cần cài đặt plugin pytest-xdist:

pip install pytest-xdist

4. Thực thi

Sử dụng tham số -n theo sau là số lượng workers (thường chọn số lượng bằng số nhân CPU của máy).

  • Ví dụ chạy với 3 workers:

    pytest -n 3

⚠️ Lưu ý quan trọng: Để chạy song song thành công, các test case phải độc lập hoàn toàn (không dùng chung 1 tài khoản đang login, không xóa dữ liệu của nhau).

 

5. Trường hợp Đa người dùng Đăng nhập: Performance Testing

Khi bạn muốn kiểm tra trường hợp nhiều người dùng đăng nhập cùng lúc (hoặc thực hiện bất kỳ hành động nào cùng lúc) để xem hệ thống có bị sập hay chậm không, đó không còn là Functional Parallel Testing nữa, mà là Performance Testing (Kiểm thử Hiệu năng) hay cụ thể hơn là Load Testing (Kiểm thử Tải).

Mục đích của Load Testing

Kiểm tra khả năng chịu tải của máy chủ, cơ sở dữ liệu và mạng khi có một lượng lớn yêu cầu cùng đổ về.

  • Mục đích chính: Đánh giá độ ổn định, tốc độ phản hồi (Response Time) và khả năng mở rộng (Scalability) của hệ thống.

  • Công cụ thường dùng: JMeter, Locust, k6.

  • Số lượng: Thường là hàng trăm, hàng nghìn (hoặc hơn) người dùng ảo (Virtual Users).

Ví dụ Test: 1000 Người dùng Đăng nhập Cùng lúc

Để mô phỏng 1000 người dùng đăng nhập vào hệ thống (ví dụ: https://hrm.example.com/login), bạn cần dùng công cụ Load Testing.

Công cụ được khuyến nghị: Locust (Python)

Locust là một framework kiểm thử tải bằng Python, cho phép bạn định nghĩa hành vi người dùng bằng code Python.

  1. Cài đặt:

    pip install locust

     

  2. Tạo file locustfile.py:

    from locust import HttpUser, task, between
    
    class WebsiteUser(HttpUser):
        # Người dùng sẽ chờ từ 1 đến 2 giây giữa các tác vụ
        wait_time = between(1, 2)
    
        # Địa chỉ cơ sở của hệ thống
        host = "https://hrm.example.com" 
    
        @task
        def login(self):
            # 1. Gửi yêu cầu POST đến endpoint đăng nhập
            # Sử dụng một payload (tải trọng) chứa thông tin đăng nhập
            login_payload = {
                "username": "user_1000", # Tên người dùng mẫu
                "password": "password123"
            }
    
            # Locust sẽ tự động tạo ra 1000 yêu cầu POST này
            response = self.client.post("/api/login", json=login_payload)
    
            # Kiểm tra xem đăng nhập có thành công không
            if response.status_code == 200:
                print("Login successful")
            else:
                print(f"Login failed with status code: {response.status_code}")

     

  3. Thực thi:

    locust -f locustfile.py

     

  4. Quan sát: Mở trình duyệt truy cập http://localhost:8089. Bạn sẽ thiết lập:

    • Number of users (Sô lượng người dùng): 1000

    • Spawn rate (Tần suất xuất hiện): 10 users/giây

Locust sẽ gửi 1000 yêu cầu đăng nhập đến server trong 100 giây và hiển thị:

  • Response Time (Thời gian phản hồi): Bao lâu để server xử lý yêu cầu.

  • Requests per Second (RPS): Số lượng yêu cầu mà server có thể xử lý mỗi giây.

  • Failure Rate (Tỷ lệ thất bại): Có bao nhiêu yêu cầu bị lỗi (lỗi 500, lỗi timeout).


Tóm lại:

  • Playwright/Pytest: Dùng để chạy song song một ít test case (dưới 10) để xác nhận chức năng là đúng.

  • Locust/JMeter: Dùng để chạy song song hàng trăm/nghìn người dùng ảo để đánh giá hiệu năng của server.


🧠 III. Chạy trên đa trình duyệt (Multi-browser)

Web hiện đại cần chạy tốt trên Google Chrome (Chromium), Firefox, và Safari (WebKit). Playwright cho phép bạn chạy toàn bộ bộ test trên các engine này.

  • Ví dụ HTML: Ứng dụng của bạn có tính năng đặc thù mà Firefox xử lý khác Chromium.

  • Ví dụ Automation:

    # Chạy trên Chromium (Mặc định)
    pytest --browser chromium
    
    # Chạy trên Firefox
    pytest --browser firefox
    
    # Chạy trên Safari (WebKit)
    pytest --browser webkit
  • Chạy song song cả 3 trình duyệt:

    pytest --browser chromium --browser firefox --browser webkit


🔍 TÓM TẮT KIẾN THỨC

Công cụ/Lệnh Tình huống sử dụng Ghi nhớ
PWDEBUG=1 Cần can thiệp trực tiếp vào quá trình chạy để tìm lỗi. Dừng trình duyệt lại cho bạn thao tác.
--tracing on Lưu lại "bằng chứng" để phân tích sau khi test xong. Xem được Video, DOM snapshot và Network.
pytest -n X Cần giảm thời gian chạy test suite. Cần cài pytest-xdist.
--browser webkit Cần kiểm tra giao diện trên trình duyệt Safari. Không cần máy Mac vẫn chạy được Safari engine.

 

🧠 IV. Allure Report

1) Khái niệm

HTML report (pytest-html)

  • một plugin của pytest tạo ra 1 file .html (thường là “1 trang report”) sau khi chạy test.

  • Mục tiêu: nhanh, gọn, mở file là xem, phù hợp check kết quả tổng quan.

Allure report

  • Allure không chỉ là “report”, mà là một hệ sinh thái reporting.

  • Pytest sẽ sinh ra raw results (thư mục allure-results/), sau đó Allure CLI sẽ render thành report dạng web (allure-report/) hoặc mở trực tiếp bằng allure serve.

  • Mục tiêu: report giàu thông tin, có suites, steps, attachments, history, trend, phù hợp CI/CD và phân tích lỗi sâu.


2) Khác nhau cốt lõi 

Output

  • pytest-html: 1 file report.html (hoặc vài file tĩnh).

  • Allure:

    • allure-results/ (json + attachments)

    • rồi render ra site allure-report/

Khả năng mô tả test (steps / story / feature / severity)

  • pytest-html: hỗ trợ cơ bản (pass/fail, duration, logs), muốn “đẹp/chuẩn” phải custom khá nhiều.

  • Allure: sinh ra để làm việc đó: @allure.feature, @allure.story, @allure.severity, allure.step(...), v.v.

Attachments (screenshot, video, trace, request/response)

  • pytest-html: attach được screenshot (thường base64 hoặc link), nhưng càng nhiều attachment càng nặng và custom phức tạp.

  • Allure: attach rất “native”: screenshot/video/trace/json/text đều có chỗ hiển thị rõ ràng, gọn.

CI/CD & xu hướng (history/trends)

  • pytest-html: thường là “report cho lần chạy đó”.

  • Allure: mạnh về history + trend, dễ xem chất lượng theo thời gian (nếu bạn lưu history trong pipeline).


3) Ưu / nhược điểm 

A) pytest-html (HTML report)

Ưu

  • Setup cực nhanh, ít phụ thuộc.

  • Ra 1 file → share dễ (đính kèm email/slack).

  • Nhẹ, phù hợp team nhỏ hoặc chạy local.

Nhược

  • Ít “ngữ nghĩa testing” (feature/story/step).

  • Khi muốn advanced (grouping, attach nhiều thứ, custom layout) → dễ thành “tự chế”.

  • Không mạnh về trend/history.

Hợp dùng khi

  • Bạn cần report nhanh – đơn giản – dễ share.

  • Dự án nhỏ, hoặc mục tiêu là “có report để xem pass/fail”.


B) Allure report

Ưu

  • Report “xịn” cho automation: steps, suites, tags, severity, attachment.

  • Debug rất sướng: click là thấy step + screenshot/trace/log.

  • Hợp CI/CD: có thể publish như artifact, có history/trend.

Nhược

  • Cần thêm công cụ: Allure CLI / Java runtime (tùy cách cài), nhiều project phải cấu hình CI thêm bước.

  • Pipeline cần lưu allure-results + history nếu muốn trend.

  • Ban đầu hơi “nhiều thứ phải hiểu” hơn html report.

Hợp dùng khi

  • Dự án vừa/lớn, chạy CI thường xuyên, cần phân tích lỗi sâu.

  • Bạn muốn chuẩn hoá report theo feature/story, attach trace/video/screenshot.


4) Cách sử dụng với Playwright Python (pytest)

4.1 Cài Python packages (pytest adapter)

Chạy:

pip install pytest allure-pytest

allure-pytest là plugin để pytest xuất “allure results” (raw data).


4.2 Cài Allure Commandline (để mở report)

Allure report cần Allure CLI để generate & open.

macOS (Homebrew):

1️⃣ Chạy:

echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"

2️⃣ Check:

brew --version

3️⃣ Cài Allure:

brew install allure

4️⃣ Open report:

allure open allure-report

 

Windows (Scoop – khuyên dùng):

1. Mở PowerShell (Run as Admin):

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
irm get.scoop.sh | iex

Verify:

scoop --version

Bước 2: Cài Allure

scoop install allure

Verify:

allure --version

Linux (tùy distro):

  • Có thể dùng package manager hoặc tải release từ GitHub của Allure.

Kiểm tra:

allure --version

 

5 Cấu trúc project khuyên dùng 

Ví dụ:

 
playwright-project/
│
├─ tests/
│   ├─ test_login.py
│   └─ ...
├─ pages/
│   └─ ...
├─ conftest.py
├─ pytest.ini
├─ requirements.txt
├─ allure-results/     (auto generate - nên gitignore)
└─ allure-report/      (auto generate - nên gitignore)
​

.gitignore nên có:

allure-results/
allure-report/
test-results/
playwright-report/
*.zip


6) Chạy test và sinh Allure report 

6.1 Run pytest để tạo allure-results

pytest -s -q --alluredir=allure-results

Giải thích:

  • --alluredir=... là nơi pytest dump raw results cho Allure


6.2 Generate report (HTML report folder)

allure generate allure-results -o allure-report --clean

6.3 Open report

allure open allure-report


7) Setup pytest.ini để chuẩn hóa 

Tạo pytest.ini:

[pytest]
addopts = -ra -q
testpaths = tests
markers =
    smoke: Smoke tests
    regression: Regression tests

Nếu muốn luôn auto alluredir khi chạy:

[pytest]
addopts = -ra -q --alluredir=allure-results

 

8) Viết test “đẹp” trong Allure 

8.1 Basic: title + description + severity

import allure

@allure.title("Login success with valid credentials")
@allure.description("Verify user can login and see dashboard.")
@allure.severity(allure.severity_level.CRITICAL)
def test_login_success(login_page):
    login_page.login("admin", "admin123")
    assert login_page.is_dashboard_visible()
 


8.2 Steps rõ ràng

import allure

def test_login_steps(login_page):
    with allure.step("Open login page"):
        login_page.open()

    with allure.step("Fill username/password and submit"):
        login_page.login("admin", "admin123")

    with allure.step("Verify dashboard is visible"):
        assert login_page.is_dashboard_visible()



 

8.3 Gắn nhãn epic/feature/story (phân nhóm)

import allure

@allure.epic("OrangeHRM")
@allure.feature("Authentication")
@allure.story("Login")
def test_login_success(login_page):
    ...


9) Attachments: screenshot / html / logs 

9.1 Attach screenshot thủ công (khi cần)

import allure

def attach_screenshot(page, name="screenshot"):
    png = page.screenshot(full_page=True)
    allure.attach(png, name=name, attachment_type=allure.attachment_type.PNG)


9.2 Auto attach screenshot khi fail (khuyên dùng)

Trong conftest.py (pytest hook), ý tưởng là:

  • Nếu test failed

  • Lấy page fixture

  • Chụp screenshot + attach

Ví dụ pattern phổ biến (tùy framework của bạn đang expose page ra sao):

import allure
import pytest

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    report = outcome.get_result()

    if report.when == "call" and report.failed:
        page = item.funcargs.get("page")
        if page:
            png = page.screenshot(full_page=True)
            allure.attach(png, name="Failure screenshot", attachment_type=allure.attachment_type.PNG)

Lưu ý: đoạn này hoạt động tốt khi bạn có fixture tên page. Nếu bạn dùng fixture custom (vd logged_in_page), đổi key tương ứng.


9.3 Attach HTML / response JSON (khi debug API/UI)

 
allure.attach(page.content(), name="DOM", attachment_type=allure.attachment_type.HTML)
allure.attach(str(response_json), name="API response", attachment_type=allure.attachment_type.JSON)
​

 

10) Best practices để report “dễ đọc” 

✅ 1 test = 1 ý chính (không nhồi nhiều assertion unrelated)
✅ Dùng allure.step() cho các bước quan trọng (Open/Login/Verify)
✅ Đính kèm evidence khi fail (screenshot + trace)
✅ Gắn nhãn:

  • epic/feature/story để lọc

  • severity để ưu tiên

  • link tới ticket (Jira) nếu có

Ví dụ link:

@allure.link("https://jira.company/browse/ABC-123", name="ABC-123")
def test_x():
    ...


11) Tích hợp CI (mức cơ bản) 

12.1 Ý tưởng CI flow

  1. Chạy test tạo allure-results/

  2. Lưu allure-results như artifact

  3. (Option) Generate allure-report/ và publish

Lưu ý: CI thường không “open report”, mà upload artifact để tải về.


12) Bài tập thực hành 

  1. Cài allure-pytest và Allure CLI

  2. Chạy:

    • pytest --alluredir=allure-results

    • allure generate ...

    • allure open ...

  3. Chọn 1 test login:

    • Thêm @allure.title, @allure.severity

    • Thêm 3 allure.step()

  4. Implement auto screenshot on fail trong conftest.py

  5. (Nâng cao) Bật tracing và attach trace.zip khi fail

 

 

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