Hoot unit test kiểm một mảnh code — gọi hàm, so kết quả. Nhưng phần mềm thật hỏng ở chỗ khác: người dùng bấm nút A, điền ô B, chuyển sang màn hình C, và đâu đó trong chuỗi đó có gì sai. Kiểm cả luồng ấy cần một công cụ khác: tour. Tour là một kịch bản mô phỏng người dùng đi qua nhiều bước trên giao diện thật — Odoo bấm và điền hộ bạn, rồi báo luồng có chạy trót lọt không.

Tour: danh sách các bước trên UI thật

Một tour là một object đăng ký vào category web_tour.tours của registry, gồm url (nơi bắt đầu) và steps (mảng các bước). Mỗi bước có trigger (chờ một phần tử xuất hiện) và run (hành động: bấm, gõ chữ, hay một hàm):

Ảnh chụp đoạn mã nền tối file quan_tour js, gọi registry category web_tour.tours add với tên quan_ca_phe_tour và object có url odoo action-929 là nơi tour bắt đầu, steps là hàm trả về mảng hai bước. Bước một trigger là o_action_manager h2 chứa Bảng điều khiển kèm chú thích trigger chờ phần tử xuất hiện rồi mới sang bước sau, content Đây là bảng điều khiển thẻ thành viên, tooltipPosition bottom. Bước hai trigger là card chứa Tổng điểm, content Ô này hiển thị tổng điểm của tất cả thẻ, run click kèm chú thích hành động bấm vào ô. Cuối cùng chú thích chạy bằng odoo startTour hoặc HttpCase start_tour trong test Python

Hình 1: Một tour hai bước. trigger là một selector CSS — tour chờ phần tử đó xuất hiện rồi mới tiếp (đây là cách tour đồng bộ với UI bất đồng bộ, không cần sleep). content là chú thích hiện trong bong bóng (dùng cho onboarding). run là hành động: "click", "edit <chữ>" (gõ vào ô), hay một hàm tuỳ ý. Tour đăng ký vào web_tour.tours.

Chạy thật: SUCCEEDED

Tour kích hoạt bằng odoo.startTour("tên") trong trình duyệt, hoặc trong một test Python bằng HttpCase.start_tour(url, "tên", login=...) — đó là cách CI chạy tour tự động. Mình chạy tour trên dashboard và bắt console:

Ảnh chụp console thật khi chạy odoo startTour quan_ca_phe_tour bắt bằng Playwright. Dòng một ghi 1 trên 2 Tour quan_ca_phe_tour mũi tên Step Đây là bảng điều khiển thẻ thành viên kèm trigger o_action_manager h2 chứa Bảng điều khiển. Dòng hai ghi 2 trên 2 Tour quan_ca_phe_tour mũi tên Step Ô này hiển thị tổng điểm của tất cả thẻ kèm trigger card chứa Tổng điểm. Dòng tiếp theo tour succeeded, và một khung viền ASCII màu xanh lá ghi TOUR quan_ca_phe_tour SUCCEEDED

Hình 2: Kết quả thật. Tour chạy qua [1/2] rồi [2/2] — mỗi dòng ghi bước và trigger đang chờ — rồi kết luận tour succeeded với khung "TOUR quan_ca_phe_tour SUCCEEDED". Nếu một trigger không bao giờ xuất hiện (vì UI hỏng), tour thất bại và báo đúng bước kẹt — đó chính là giá trị kiểm thử: nó bắt được luồng gãy ở đâu.

Tour so với Hoot unit test

Hai công cụ, hai tầng:

Hoot unit test Tour
Kiểm cái gì một hàm/component cả một luồng nhiều bước
Chạy trên code cô lập UI thật, server thật
Nhanh/chậm rất nhanh chậm hơn (dựng cả app)
Bắt được logic sai tích hợp gãy, nút mất, luồng đứt

Dùng cả hai: unit test cho phần lớn logic (nhanh, nhiều), tour cho vài luồng quan trọng (đăng ký, đặt hàng, thanh toán). Đừng viết tour cho mọi thứ — chúng chậm và giòn hơn.

Hai công dụng, một cơ chế

Điều hay: tour vừa để kiểm thử vừa để hướng dẫn onboarding. Cùng một định nghĩa:

  • Khai vào web.assets_tests → tour chạy trong test tự động (CI), không hiện cho người dùng.
  • Khai vào web.assets_backend và gắn với một điều kiện → tour chạy cho người dùng thật, hiện bong bóng content dẫn họ qua các bước (kiểu "hướng dẫn 5 bước đầu"). Đó là lý do mỗi bước có content và tooltipPosition.

Ba ý mang về

  1. Tour mô phỏng người dùng đi qua nhiều bước trên UI thật — kiểm thử end-to-end thứ mà unit test không thấy: tích hợp gãy, nút biến mất, luồng đứt giữa chừng. Đăng ký vào registry.category("web_tour.tours") với url + steps.
  2. Mỗi bước có trigger (chờ selector xuất hiện) và run (hành động: click / "edit chữ" / hàm). trigger là cách tour tự đồng bộ với UI bất đồng bộ — không cần sleep. Chạy bằng odoo.startTour(...) hoặc HttpCase.start_tour(...) trong test Python.
  3. Dùng cả unit test lẫn tour, đúng tầng: unit test cho logic (nhanh, nhiều); tour cho vài luồng quan trọng (chậm, ít). Cùng một tour còn dùng lại được làm hướng dẫn onboarding khi khai vào bundle backend.

Ta đã đi hết mảng lập trình web client và kiểm thử. Phần sau chuyển sang mảng website: viết một snippet — khối nội dung kéo–thả mà người dùng tự sắp vào trang bằng trình dựng website của Odoo.