Manual sang automation: để Claude Code viết test Playwright + Python, chạy thật trên web của bạn
Đặt vấn đề
Tester nắm chắc kịch bản kiểm thử, nhưng đến bước automation thì khựng lại vì cú pháp, selector, xử lý bất đồng bộ — toàn thứ nghe như việc của lập trình viên. Claude Code chạy trong thư mục dự án, đọc được cấu trúc trang thật và sinh file test Playwright/Python trực tiếp trong repo. Bài này dùng maiqai.com làm ví dụ thật — mọi test đều đã chạy lại được bằng pytest trên môi trường thật. Dù vậy, script AI sinh ra vẫn là bản nháp cần rà, không phải kết quả tin ngay.
🚀 Thiết lập trong 5 bước
Mất khoảng 10-15 phút lần đầu, sau đó chỉ việc dùng.
- 1Bước 1 — Cài Playwright cho PythonTrong thư mục dự án test, chạy `pip install pytest-playwright` rồi `playwright install` (lệnh sau tải trình duyệt Chromium/Firefox/WebKit về). Đây cũng đúng là cách bài này đã cài để chạy các ví dụ bên dưới.
- 2Bước 2 — Mở Claude Code, cho nó xem trang cần testMở Claude Code tại thư mục test. Chỉ cho nó địa chỉ trang cần kiểm (ví dụ https://maiqai.com) và mô tả các phần chính: tiêu đề lớn, menu, ô tìm kiếm. Mục tiêu là để AI nắm cấu trúc trang trước khi sinh code, nhờ vậy locator sát thực tế hơn.
- 3Bước 3 — Yêu cầu sinh test theo Page ObjectLưu bộ test case của trang (mỗi case gồm Thao tác + Verify) thành một file, ví dụ `test-cases/trang-chu.md`. Rồi dùng Prompt 1 bên dưới để Claude Code đọc file đó và sinh file test: một class Page Object (gom locator + hành động của trang) và các hàm test (mỗi case một test, có assertion bằng expect). Tổ chức theo Page Object giúp khi giao diện đổi bạn chỉ sửa một chỗ. Bắt đầu với đúng một trang — trang chủ — cho dễ kiểm soát.Cần kịch bản test trước? Xem bài Viết test case từ user story
- 4Bước 4 — Chạy pytest, đọc kết quả, sửa khi đỏChạy `pytest --base-url https://maiqai.com -q`. Lần đầu thường gặp lỗi 'strict mode' (locator khớp nhiều phần tử) hoặc selector chưa đúng — dán lỗi cho Claude Code để nó sửa (Prompt 2). Thêm `--headed` để xem trình duyệt chạy trực tiếp, hoặc bật trace khi cần soi từng bước.
- 5Bước 5 — Gộp data-driven & mở rộng, rồi mới tính CIKhi trang đầu đã xanh và bạn đã rà đúng, gộp các case cùng dạng (nhiều từ khóa, nhiều bộ dữ liệu) thành một test data-driven bằng `@pytest.mark.parametrize` cho gọn (Prompt 3), rồi mở rộng sang trang khác. Khi bộ test đủ ổn định mới đưa vào CI (GitHub Actions...) — đừng vội tự động hóa khi test còn chập chờn.
🔍 3 prompt — kèm chỗ AI hay sai cần bắt
AI sinh kết quả chỉ trong vài giây — việc của bạn là kiểm lại. Mỗi prompt kèm ví dụ kết quả và 🔍 Góc soi lỗi của Tester (chỗ AI hay sai, nên xem trước khi dùng). Bấm Copy → dán vào Claude Code / ChatGPT.
Biến bộ test case của trang chủ thành test Playwright + pytest chạy được, tổ chức theo Page Object.
Đọc bộ test case cho trang chủ https://maiqai.com trong file `test-cases/trang-chu.md` (mỗi case gồm phần Thao tác và Verify), rồi viết test tự động bằng Playwright Python (pytest-playwright), tổ chức theo Page Object Model:
- Một class TrangChu: gom locator và hành động (mở trang, lấy tiêu đề, bấm menu, nhập ô tìm kiếm rồi bấm Tìm).
- Mỗi test case thành một hàm test_...: thực hiện đúng phần 'Thao tác', rồi dùng expect() để kiểm đúng phần 'Verify'.
Ưu tiên locator theo vai trò/nhãn/nội dung (get_by_role, get_by_label); nếu phần tử không có vai trò/nhãn phù hợp (ví dụ ô tìm kiếm) thì dùng thuộc tính ổn định như name, tránh selector phụ thuộc class/style dễ vỡ. Mở trang để xác nhận selector trước khi viết; chỗ nào chưa chắc thì ghi TODO, đừng đoán bừa. Dùng base URL qua --base-url để goto('/').AI hay đoán selector chưa khớp trang thật nên lần chạy đầu dễ đỏ — phải chạy thật rồi sửa. Locator get_by_role bền hơn CSS. Đừng tin 'passed' ngay: kiểm xem assertion có thật sự khẳng định đúng kết quả (vào đúng trang, đúng nội dung) chứ không chỉ 'có phần tử nào đó'.
Khi test đỏ — nhất là lỗi strict mode do locator khớp nhiều phần tử — nhờ Claude Code đọc lỗi rồi sửa.
Test Playwright của tôi chạy pytest bị lỗi. Hãy đọc thông báo lỗi ở dưới, chỉ ra nguyên nhân, sửa code cho đúng và giải thích ngắn gọn vì sao. Nếu lỗi do locator (sai hoặc khớp nhiều phần tử), ưu tiên locator rõ ràng, ổn định. Lỗi pytest: [DÁN LỖI VÀO ĐÂY]
Lỗi strict mode rất hay gặp khi trang có nhiều liên kết/nút trùng chữ — đừng vá bằng .first cho qua chuyện, hãy đặt locator rõ ràng để không bấm nhầm. Mỗi lần sửa, chạy lại để chắc, đừng sửa hàng loạt rồi mới chạy.
Test data-driven = viết MỘT test rồi cho nó chạy lại với nhiều bộ dữ liệu khác nhau, thay vì chép test thành nhiều bản gần giống nhau. Ở đây: gộp các trường hợp tìm kiếm (nhiều từ khóa) thành một test lặp qua danh sách từ khóa — đỡ lặp code, dễ thêm trường hợp mới.
Gộp các trường hợp tìm kiếm cùng dạng thành MỘT test data-driven bằng @pytest.mark.parametrize, cho các từ khóa: "test case", "requirement", "automation". Với mỗi từ khóa: tìm trên trang chủ rồi khẳng định chuyển sang /tim-kiem và có ít nhất một kết quả bài viết. Giữ phong cách locator như các test trước. Đặt tên rõ để khi đỏ biết ngay từ khóa nào hỏng.
Data-driven gọn, nhưng khi một từ khóa đỏ phải biết ngay từ nào — pytest tự gắn tham số vào tên test (test_tim_kiem_co_ket_qua[automation]). Cẩn thận phân biệt dữ liệu minh họa với dữ liệu thật; đừng để lộ tài khoản/dữ liệu nhạy cảm trong script.
📌 Tóm lại
AI rút ngắn rất nhiều quãng đường từ kịch bản sang test chạy được, nhưng chọn cái gì đáng kiểm và xác nhận assertion đúng nghĩa nghiệp vụ vẫn là việc của con người. Toàn bộ ví dụ ở đây đã chạy thật trên một trang web thực — bạn hoàn toàn có thể làm lại. Hãy dùng AI để đi nhanh hơn, không phải để khỏi cần hiểu, vì một test tự động viết sai sẽ âm thầm bỏ lọt lỗi mà không ai hay.