Mặc định, Pytest tự động thu thập các bản ghi mức WARNING trở lên. Khi một test thất bại, thông tin log sẽ được hiển thị cùng với stdout và stderr trong phần tóm tắt kết quả.
Khi chạy lệnh:
pytest
Kết quả lỗi sẽ có dạng:
----------------------- Captured stdlog call ----------------------
test_example.py 26 WARNING nội dung log
----------------------- Captured stdout call ----------------------
nội dung stdout
----------------------- Captured stderr call ----------------------
nội dung stderr
==================== 2 failed in 0.02 seconds =====================
Bạn có thể tùy chỉnh định dạng hiển thị log bằng cách dùng các tùy chọn dòng lệnh:
pytest --log-format="%(asctime)s [%(levelname)s] %(message)s" \
--log-date-format="%d/%m/%Y %H:%M:%S"
Hoặc cấu hình trong file pytest.ini:
[pytest]
log_format = %(asctime)s [%(levelname)s] %(message)s
log_date_format = %d/%m/%Y %H:%M:%S
Để tắt hoàn toàn việc ghi lại log/stdout/stderr khi test thất bại:
pytest --show-capture=no
Sử dụng fixture caplog để kiểm soát log trong test
Fixture caplog cho phép bạn điều chỉnh mức độ log trong quá trình test:
def test_demo_log_level(caplog):
caplog.set_level("INFO")
# mã test ở đây
Có thể chỉ định logger cụ thể:
def test_specific_logger(caplog):
caplog.set_level("CRITICAL", logger="app.module_x")
Dùng context manager để thay đổi tạm thời:
def test_temporary_level(caplog):
with caplog.at_level("DEBUG", logger="app.utils"):
# đoạn code cần debug
pass
Truy cập các bản ghi đã thu thập:
def test_validate_logs(caplog):
some_function()
assert not any(r.levelname == "ERROR" for r in caplog.records)
assert "lỗi nghiêm trọng" not in caplog.text
Kiểm tra nhanh bằng tuple:
def test_log_content(caplog):
logging.info("Xin chào %s", "Pytest")
assert caplog.record_tuples == [("root", 20, "Xin chào Pytest")]
Xóa log đã ghi trong test:
def test_with_clearing(caplog):
noisy_function()
caplog.clear()
clean_test_logic()
assert [r.message for r in caplog.records] == ["Thành công"]
Truy cập log từ các giai đoạn khác (setup/call/teardown):
@pytest.fixture
def safe_env(caplog):
env = setup_environment()
yield env
for phase in ("setup", "call"):
warnings = [
rec.message
for rec in caplog.get_records(phase)
if rec.levelno >= logging.WARNING
]
if warnings:
pytest.fail(f"Cảnh báo phát sinh: {warnings}")
Kích hoạt log trực tiếp ra console
Thêm vào pytest.ini:
[pytest]
log_cli = true
log_cli_level = INFO
log_cli_format = %(asctime)s | %(name)s | %(levelname)s | %(message)s
Hoặc dùng tùy chọn dòng lệnh:
pytest --log-cli-level=DEBUG --log-cli-format="%(message)s"
Ghi log ra file
Cấu hình trong pytest.ini:
[pytest]
log_file = logs/test_run.log
log_file_level = DEBUG
log_file_format = %(asctime)s - %(levelname)s - %(message)s
Hoặc đặt tên file log động trong conftest.py:
import os
from datetime import datetime
def pytest_configure(config):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
log_dir = os.path.join(config.rootdir, "logs")
os.makedirs(log_dir, exist_ok=True)
config.option.log_file = os.path.join(log_dir, f"test_{timestamp}.log")
Lưu ý về tương thích phiên bản
Tính năng log tích hợp thay thế plugin pytest-catchlog cũ. Để tắt tính năng log mới và quay lại dùng plugin cũ:
[pytest]
addopts = -p no:logging
Từ Pytest 3.4, hành vi mặc định thay đổi:
- Mức log không còn bị ép buộc trừ khi bạn chỉ định rõ ràng.
- Log trực tiếp ra console bị tắt mặc định — cần bật
log_cli=true. - Log CLI giờ xuất ra
sys.stdout, không cần dùng-s.
Để khôi phục hành vi cũ (giống Pytest 3.3):
[pytest]
log_cli = true
log_level = NOTSET