Pytest API Tham Khảo: Quản Lý Fixture và Các Built-in Fixture Quan Trọng

Fixture trong Pytest

Fixture là một cơ chế trung tâm trong Pytest, cho phép chia sẻ dữ liệu, trạng thái hoặc tài nguyên giữa các test và fixture khác. Một hàm test hoặc fixture khác có thể yêu cầu sử dụng fixture thông qua tham số hàm. Ví dụ:

def test_output(capsys):
    print("hello")
    captured = capsys.readouterr()
    assert captured.out == "hello\n"

Một fixture cũng có thể phụ thuộc vào fixture khác:

@pytest.fixture
def db_session(tmp_path):
    db_file = tmp_path / "database.sqlite"
    return connect_to_db(str(db_file))

@pytest.fixture – Định nghĩa fixture

Được dùng như một decorator để đánh dấu một hàm là fixture. Cú pháp:

@pytest.fixture(scope="function", params=None, autouse=False, ids=None, name=None)
  • scope: Phạm vi hoạt động của fixture – "function" (mặc định), "class", "module", "package" (thử nghiệm), hoặc "session".
  • params: Danh sách giá trị để tạo nhiều phiên bản test từ cùng một fixture.
  • autouse: Nếu True, fixture tự động được kích hoạt mà không cần khai báo tường minh.
  • ids: Tên tùy chỉnh cho từng giá trị trong params, giúp dễ đọc kết quả test.
  • name: Đặt tên riêng cho fixture, hữu ích khi muốn tránh xung đột tên trong cùng module.

Fixture có thể trả về giá trị bằng return hoặc yield. Với yield, phần code sau đó sẽ được thực thi như bước dọn dẹp dù test thành công hay thất bại.

Các Built-in Fixture Chính

config.cache – Lưu trữ trạng thái giữa các lần chạy

Cho phép lưu và lấy lại dữ liệu giữa các lần chạy test, thường dùng trong plugin hoặc setup nâng cao.

  • cache.get(key, default): Lấy giá trị theo khóa; trả về mặc định nếu không tồn tại.
  • cache.set(key, value): Lưu giá trị với kiểu dữ liệu Python cơ bản (dict, list, str...).
  • cache.makedir(name): Tạo thư mục tạm để lưu file (ví dụ: dump database).

capsys & capfd – Bắt đầu ra stdout/stderr

Dùng để kiểm tra đầu ra in ra màn hình.

def test_print(capsys):
    print("Testing capture")
    captured = capsys.readouterr()
    assert "Testing" in captured.out
  • capsys: Bắt dạng text từ sys.stdout/sys.stderr.
  • capsysbinary: Bắt dạng bytes.
  • capfd: Bắt output từ file descriptor (phù hợp với lệnh hệ thống).
  • capfdbinary: Phiên bản bytes của capfd.

doctest_namespace – Hỗ trợ doctest

Cung cấp namespace cho các ví dụ trong docstring. Thường dùng với autouse=True:

@pytest.fixture(autouse=True)
def add_numpy(doctest_namespace):
    doctest_namespace["np"] = numpy

request – Truy cập ngữ cảnh test

Cho phép truy cập thông tin runtime như tên test, tham số, cấu hình…

def test_info(request):
    print(f"Running {request.node.name}")
    if request.cls:
        print(f"In class {request.cls.__name__}")

Một số thuộc tính quan trọng:

  • request.function: Hàm test hiện tại.
  • request.module: Module chứa test.
  • request.config: Đối tượng cấu hình pytest.
  • request.param: Giá trị tham số nếu fixture được parameter hóa.
  • request.addfinalizer(): Đăng ký hàm dọn dẹp.
  • request.getfixturevalue('name'): Gọi fixture động (thay thế getfuncargvalue đã lỗi thời).

pytestconfig – Truy cập cấu hình toàn cục

Trả về đối tượng Config để kiểm tra cờ dòng lệnh:

def test_verbose(pytestconfig):
    if pytestconfig.getoption("verbose") > 0:
        print("Verbose mode enabled")

record_property & record_testsuite_property – Ghi thuộc tính vào báo cáo

Dùng để thêm metadata vào kết quả test:

def test_with_metadata(record_property):
    record_property("issue", "BUG-123")
    record_property("environment", "staging")

record_testsuite_property có phạm vi session, dùng để ghi thông tin toàn bộ suite (ví dụ: JUnit XML).

caplog – Kiểm tra log

Bắt và kiểm tra các thông điệp log:

def test_logging(caplog):
    with caplog.at_level(logging.INFO):
        some_function_that_logs()
    assert "User logged in" in caplog.text
    assert ("my_logger", logging.ERROR, "Failed") in caplog.record_tuples

Các thuộc tính:

  • caplog.records: Danh sách đối tượng LogRecord.
  • caplog.text: Chuỗi log đã định dạng.
  • caplog.messages: Danh sách message đã xử lý.
  • caplog.clear(): Xóa log đã bắt.
  • caplog.set_level(): Điều chỉnh mức log.

monkeypatch – Thay đổi tạm thời hệ thống

Dùng để mock biến môi trường, thuộc tính, hàm…

def test_env_var(monkeypatch):
    monkeypatch.setenv("API_KEY", "fake123")
    assert get_api_key() == "fake123"

def test_attribute(monkeypatch):
    monkeypatch.setattr(os, 'getcwd', lambda: "/fake/path")
    assert os.getcwd() == "/fake/path"

Tất cả thay đổi sẽ tự động hoàn tác sau khi test kết thúc.

tmp_path & tmpdir – Thư mục tạm

Cung cấp đường dẫn đến thư mục tạm duy nhất cho mỗi test:

def test_write_file(tmp_path):
    data_file = tmp_path / "sample.txt"
    data_file.write_text("Hello")
    assert data_file.read_text() == "Hello"
  • tmp_path: Trả về đối tượng pathlib.Path (ưu tiên dùng).
  • tmpdir: Dạng cũ, dùng py.path.local.

Các factory tương ứng (tmp_path_factory, tmpdir_factory) cho phép chia sẻ thư mục tạm ở phạm vi lớn hơn (ví dụ: module).

recwarn – Kiểm tra cảnh báo (warnings)

Ghi lại các cảnh báo Python phát sinh trong test:

def test_deprecation(recwarn):
    deprecated_function()
    assert len(recwarn) == 1
    w = recwarn.pop(DeprecationWarning)
    assert "deprecated" in str(w.message)

Hữu ích để đảm bảo mã đang di chuyển đúng hướng (ví dụ: xử lý DeprecationWarning).

testdir – Test plugin và nội bộ pytest

Dành cho việc kiểm thử plugin hoặc mở rộng pytest. Yêu cầu bật plugin:

# conftest.py
pytest_plugins = ["pytester"]

Cung cấp nhiều phương tiện để tạo file, chạy pytest nội bộ, kiểm tra đầu ra:

def test_plugin(testdir):
    testdir.makepyfile("""
        def test_something():
            assert True
    """)
    result = testdir.runpytest()
    result.assert_outcomes(passed=1)

Các phương thức chính: makepyfile(), runpytest(), inline_run(), parseconfig(), runpython().

Thẻ: pytest fixture testing python unittest

Đăng vào ngày 9 tháng 6 lúc 01:48