Ở bài trước mình đã dán hai nhãn @tagged('post_install', '-at_install') lên lớp test mà chưa giải thích. Chúng không phải trang trí — chúng quyết định thời điểm test chạy trong quá trình cài Odoo, và chọn sai là nguồn của một loại bug khó chịu: test lúc xanh lúc đỏ mà không rõ vì sao. Bài này mổ xẻ @tagged, hai nhãn at_install/post_install, và chứng minh sự khác biệt bằng log thật.
Hai thời điểm chạy test
Khi Odoo cài/nâng cấp, nó nạp lần lượt hàng trăm module. Test của module bạn có thể chạy ở hai thời điểm:
at_install(mặc định): chạy ngay sau khi module của bạn được cài, trước khi các module còn lại cài xong. Môi trường lúc này "tinh khiết" — chỉ có module bạn và những gì nó phụ thuộc.post_install: chạy sau khi TẤT CẢ module đã cài xong. Môi trường "đầy đủ", giống hệt production.
Khai bằng decorator @tagged:

Hình 1: Ba lớp test với ba cấu hình tag. TestChayLucCai không khai gì → mặc định at_install. TestChaySauCai khai @tagged('post_install', '-at_install') — bật post_install, và dấu trừ -at_install tắt nhãn mặc định (nếu không, nó chạy cả hai lần). TestCoTagRieng thêm một tag tuỳ biến 'chi_toi' để lọc riêng sau này.
Chứng minh bằng log thật
Đây là phần thú vị. Mình chạy cả ba test trên blog19 và đọc kỹ thứ tự trong log — nó phơi bày đúng cơ chế:

Hình 2: Thật, và rất rõ. Ở phần 1: test at_install chạy ngay sau "Loading module quan_ca_phe (94/175)" — mới cài 94 trên 175 module! Còn test post_install chạy sau dòng "175 modules loaded" — khi mọi module đã xong. Hai test chạy ở hai thời điểm hoàn toàn khác nhau của tiến trình cài. Phần 2: lọc --test-tags=chi_toi → chỉ 1 test chạy, hai lớp kia bị bỏ qua.
Vì sao chọn sai gây "test đỏ ngẫu nhiên"
Giờ hiểu tại sao nhãn này quan trọng. Giả sử test của bạn kiểm một tính năng đụng tới module khác — ví dụ tạo một đơn bán hàng (sale), hay gọi một route của website. Nếu để test đó chạy ở at_install, mà module sale/website được cài SAU module của bạn, thì lúc test chạy chúng chưa tồn tại → test đỏ. Nhưng nếu cài theo thứ tự khác, chúng có thể đã sẵn → test xanh. Kết quả: test đỏ hay xanh phụ thuộc thứ tự cài, không phụ thuộc code — cực khó lần.
Quy tắc đơn giản:
- Test chỉ đụng model của chính module bạn → để
at_install(mặc định), chạy sớm, nhanh. - Test đụng tính năng/dữ liệu của module khác, hay cần môi trường giống production → dùng
post_install.
Khi phân vân, post_install là lựa chọn an toàn hơn — đó là lý do phần lớn test thực tế đều mang nhãn này.
Lọc test bằng --test-tags
Cú pháp --test-tags rất linh hoạt, ghép nhiều điều kiện bằng dấu phẩy:
--test-tags=/quan_ca_phe # mọi test của module quan_ca_phe
--test-tags=chi_toi # mọi test mang tag tuỳ biến 'chi_toi'
--test-tags=-slow # loại test có tag 'slow'
--test-tags=.TestChaySauCai # chỉ một lớp
--test-tags=:test_moc_tag_rieng # chỉ một method
Các tiền tố: / = module, . = lớp, : = method, - = loại trừ, không tiền tố = tên tag. Mặc định mọi test mang nhãn ngầm standard; --test-tags cho bạn chạy đúng nhóm cần trong lúc phát triển thay vì chờ toàn bộ.
Ba ý mang về
@taggedquyết định KHI NÀO test chạy:at_install(mặc định) chạy ngay sau khi cài module bạn — đã thấy nó chạy lúc mới 94/175 module;post_installchạy sau khi tất cả module cài xong (sau dòng "175 modules loaded").@tagged('post_install', '-at_install')bậtpost_installvà dấu trừ tắt nhãn mặc định. Test đụng module khác mà đểat_installsẽ đỏ ngẫu nhiên theo thứ tự cài — dùngpost_installcho an toàn.--test-tagslọc test theo module (/), lớp (.), method (:), tag tuỳ biến, và loại trừ (-) — đã chứng minh--test-tags=chi_toichỉ chạy đúng 1 lớp.
Đã biết viết test và điều khiển khi nào chúng chạy, phần còn thiếu là viết test cho tốt. Phần sau bàn về dựng dữ liệu và assert đúng cách — cách tạo dữ liệu nền gọn gàng, chọn đúng phép assert, và những cạm bẫy khiến test "xanh giả" mà không thực sự kiểm được gì.