pytest 9.2.0 phát hành ngày 27/10/2026, với thay đổi lớn nhất ở @pytest.mark.parametrize: ba tham số indirect, ids và scope giờ chỉ nhận theo từ khóa — truyền theo vị trí sẽ lỗi TypeError ngay lúc thu thập test. Bản này cũng phân loại lỗi import plugin rõ ràng hơn.

Nếu dự án của bạn dùng parametrize ở hàng trăm chỗ, hãy đọc kỹ trước khi nâng cấp: thay đổi tuy nhỏ nhưng đủ làm đỏ pipeline CI nếu code cũ truyền tham số theo vị trí — đúng kiểu lỗi mà pytest 9.2 muốn dẹp bỏ.

parametrize siết chặt: indirect, ids và scope chỉ nhận theo từ khóa

Trước đây parametrize nhận tham số theo cả vị trí lẫn từ khóa, và đó là nguồn gốc của một lỗi khó hiểu: viết @pytest.mark.parametrize("arg1", "arg2", [(1, 2)]) với ý định truyền danh sách giá trị, bạn sẽ nhận lỗi indirect fixture '(1, 2)' doesn't exist — vì danh sách đã rơi nhầm vào indirect ở vị trí thứ ba.

Từ pytest 9.2, kiểu nhầm lẫn này báo TypeError ngay lúc thu thập test, chỉ thẳng vào dòng gọi hàm. Cách viết đúng là dùng từ khóa, ví dụ indirect=True khi muốn giá trị đi qua fixture.

import pytest
@pytest.fixture
def user(request):
return request.param # nhan gia tri qua indirect
@pytest.mark.parametrize("user", ["linh", "fish"], indirect=True)
def test_greeting(user):
assert user in ("linh", "fish")

Lỗi import plugin giờ có mã thoát rõ ràng

Lỗi import plugin lúc khởi động giờ được phân loại thay vì traceback thô với mã thoát 1 chung chung. Plugin không tìm thấy sẽ thoát với mã USAGE_ERROR (4); plugin tìm thấy nhưng lỗi khi import thoát với mã INTERNAL_ERROR (3) và giữ nguyên traceback để bạn soi.

Tính năng mới đáng chú ý

Ngoài hai thay đổi trên, pytest 9.2 còn vài cải tiến nhỏ mà ai chạy bộ test lớn sẽ cảm nhận ngay:

  • Diff khi assert thất bại giờ có chú thích giải thích ký hiệu + và −, khỏi đoán dòng nào thừa, dòng nào thiếu.
  • Bật strict_markers thì tên marker trong -m được kiểm tra, gõ sai tên không còn lặng lẽ cho ra 0 test.
  • Cache module đã viết lại trong __pycache__ giờ vô hiệu bằng hash mã nguồn thay vì thời gian sửa file, nên cache sống sót sau mỗi lần checkout mới trong CI.

Chuẩn bị cho pytest 10: vài thứ sắp bị loại bỏ

Bản 9.2 dọn đường cho pytest 10: decorator yield_fixture đã lên lịch xóa, fixture scope module, package hay session định nghĩa instance method giờ bị deprecated, và truyền giá trị không phải chuỗi cho tùy chọn ini kiểu chuỗi sẽ hiện cảnh báo trước khi thành lỗi ở pytest 10.

Điều này có ý nghĩa gì với bạn

Trước khi nâng cấp, hãy rà soát codebase: tìm chỗ gọi parametrize có truyền indirect, ids hay scope theo vị trí và chuyển sang dạng từ khóa. Sau khi nâng cấp, chạy pytest --collect-only để kiểm tra collection còn sạch rồi mới chạy full suite. Nếu chưa muốn động vào code cũ ngay, ghim tạm pytest<9.2.

Bài viết liên quan

Câu hỏi thường gặp

Nâng cấp lên pytest 9.2 có làm vỡ test đang chạy không?

Chỉ khi code truyền indirect, ids hoặc scope theo vị trí, hoặc dùng -c với đường dẫn không tồn tại. Còn lại, test viết đúng chuẩn chạy bình thường.

Lỗi TypeError ở parametrize sửa thế nào?

Thêm tên tham số vào lời gọi, ví dụ đổi thành indirect=True. Chạy pytest --collect-only để soát hết các chỗ còn sót.

indirect=True dùng để làm gì?

Để giá trị parametrize đi qua fixture thay vì truyền thẳng vào test. Fixture nhận giá trị qua request.param, hữu ích khi cần setup dữ liệu hay tạo đối tượng trước mỗi ca test.

💬 Tin này ảnh hưởng tới dự án của bạn thế nào? Chia sẻ góc nhìn của bạn trong phần bình luận — mình đọc hết và sẽ tổng hợp những ý hay nhất.

Nguồn tham khảo