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:
-
Print Debugging (Logging): Thêm các câu lệnh như
console.log()hoặcprintf()để in giá trị biến ra màn hình. -
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.
-
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.
-
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).
-
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
-
Mở file code: Nhấn
F5hoặc chọn biểu tượng Run and Debug ở thanh bên trái. -
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. -
Đặt Breakpoint: Click vào dòng bạn nghi ngờ có lỗi.
-
Đ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:
-
Mở file test Python (thường dùng với
pytest). -
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.
-
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ặcpage.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.
-
Cài đặt:
pip install locust -
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}") -
Thực thi:
locust -f locustfile.py -
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)
-
Là 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ằngallure 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+historynế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-pytestlà 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:
2️⃣ Check:
3️⃣ Cài Allure:
4️⃣ Open report:
Windows (Scoop – khuyên dùng):
1. Mở PowerShell (Run as Admin):
Verify:
Bước 2: Cài 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ụ:
.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
pagefixture -
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 (vdlogged_in_page), đổi key tương ứng.
9.3 Attach HTML / response JSON (khi debug API/UI)
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:
11) Tích hợp CI (mức cơ bản)
12.1 Ý tưởng CI flow
-
Chạy test tạo
allure-results/ -
Lưu
allure-resultsnhư artifact -
(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
-
Cài
allure-pytestvà Allure CLI -
Chạy:
-
pytest --alluredir=allure-results -
allure generate ... -
allure open ...
-
-
Chọn 1 test login:
-
Thêm
@allure.title,@allure.severity -
Thêm 3
allure.step()
-
-
Implement auto screenshot on fail trong
conftest.py -
(Nâng cao) Bật tracing và attach
trace.zipkhi fail
