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
🧩 IV. Bài tập Thực hành: "Thám tử tìm lỗi"
Kịch bản: Bạn có một đoạn code cố tình viết sai Locator khiến test case thất bại.
-
Chuẩn bị file
test_fail.py:
from playwright.sync_api import Page, expect
def test_login_failure_debug(page: Page):
page.goto("https://www.saucedemo.com/")
# Cố tình sai ID: 'user-name-wrong' thay vì 'user-name'
page.locator("#user-name-wrong").fill("standard_user")
page.locator("#password").fill("secret_sauce")
page.get_by_role("button", name="Login").click()
-
Yêu cầu thực hành:
-
Bước 1: Chạy test với
pytest --tracing retain-on-failure. -
Bước 2: Sau khi test fail, mở file trace được sinh ra trong thư mục
test-results. -
Bước 3: Sử dụng Trace Viewer để soi xem tại bước nào trang web bị đứng, kiểm tra tab Logs và Console để thấy lỗi
TimeoutError: Waiting for locator("#user-name-wrong"). -
Bước 4: Dùng Playwright Inspector (
PWDEBUG=1) để chạy lại. Tại dòng lỗi, dùng tính năng Explore để lấy lại locator đúng#user-name. -
Bước 5: Sửa lại code và chạy song song với 2 workers (
pytest -n 2) để xác nhận mọi thứ đã ổn.
-
🔍 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. |
