Automate Test Logging in Python with a Simple Decorator

This guide shows how to replace repetitive print or logging calls in automated test suites by creating a reusable @log_test decorator that automatically records start, success, failure, timestamps, and execution time for each test function.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
Automate Test Logging in Python with a Simple Decorator

Why Automatic Logging Is Needed

When a test suite contains many test cases, each test often needs to log a start message, a success message, or a failure message, together with a timestamp, test name, and execution duration. Hard‑coding these log statements makes format changes cumbersome and mixes logging with test logic.

Core Idea: Wrap Test Functions with a Decorator

A Python decorator can inject logging before and after a test runs without modifying the test’s source code.

import functools
import logging
import time

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)

def log_test(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        logger = logging.getLogger(__name__)
        logger.info(f"▶ 开始执行测试: {func.__name__}")
        start_time = time.time()
        try:
            result = func(*args, **kwargs)
            elapsed = time.time() - start_time
            logger.info(f"✅ 测试通过: {func.__name__} | 耗时: {elapsed:.2f}s")
            return result
        except Exception as e:
            elapsed = time.time() - start_time
            logger.error(f"❌ 测试失败: {func.__name__} | 耗时: {elapsed:.2f}s | 错误: {e}")
            raise
    return wrapper

Usage Example

@log_test
def test_user_login_success():
    assert login("alice", "123456") is True

@log_test
def test_create_order():
    order_id = create_order(user_id=1001, items=["A", "B"])
    assert order_id > 0

@log_test
def test_api_timeout_should_fail():
    response = call_slow_api(timeout=1)
    assert response.status_code == 200  # expected to timeout

Sample Output

2026-01-24 21:40:01 - INFO - ▶ 开始执行测试: test_user_login_success
2026-01-24 21:40:01 - INFO - ✅ 测试通过: test_user_login_success | 耗时: 0.05s
2026-01-24 21:40:01 - INFO - ▶ 开始执行测试: test_create_order
2026-01-24 21:40:02 - INFO - ✅ 测试通过: test_create_order | 耗时: 0.82s
2026-01-24 21:40:02 - INFO - ▶ 开始执行测试: test_api_timeout_should_fail
2026-01-24 21:40:05 - ERROR - ❌ 测试失败: test_api_timeout_should_fail | 耗时: 3.01s | 错误: TimeoutError: API call timed out

Advanced Tips

Make the decorator configurable, e.g., @log_test(level="DEBUG"), to allow custom log levels or formats.

It works seamlessly with pytest; the decorator does not interfere with pytest’s assertion handling or reporting.

To write logs to a file, add filename="test.log" to logging.basicConfig.

Capture test arguments for richer context:

logger.info(f"▶ 执行测试: {func.__name__} (参数: {kwargs})")

.

Pythonautomated testingloggingcode-reuseDecoratorpytest
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.