Testing Guide¶
LogXide provides testing utilities to capture and assert on log output, similar to pytest's caplog fixture.
Quick Start (pytest)¶
LogXide includes a built-in pytest plugin that provides a caplog fixture automatically:
from logxide import logging
def test_logging(caplog):
logger = logging.getLogger("test")
logger.addHandler(caplog.handler)
logger.info("Hello!")
assert "Hello!" in caplog.text
assert ("test", 20, "Hello!") in caplog.record_tuples
Auto-registration
The caplog fixture is auto-registered via pyproject.toml entry point when logxide is installed. No conftest.py setup required.
LogCaptureFixture¶
For more control, use LogCaptureFixture directly:
import pytest
from logxide import logging
from logxide.testing import LogCaptureFixture
@pytest.fixture
def caplog_logxide():
fixture = LogCaptureFixture()
fixture.set_level(logging.DEBUG)
yield fixture
fixture.clear()
def test_example(caplog_logxide):
logger = logging.getLogger("test")
logger.addHandler(caplog_logxide.handler)
logger.info("Hello!")
assert "Hello!" in caplog_logxide.text
assert ("test", 20, "Hello!") in caplog_logxide.record_tuples
assert caplog_logxide.messages == ["Hello!"]
Properties¶
| Property | Type | Description |
|---|---|---|
.handler |
MemoryHandler |
The underlying Rust-backed memory handler |
.records |
list[LogRecord] |
All captured log records |
.text |
str |
All messages as newline-separated string |
.record_tuples |
list[tuple[str, int, str]] |
(logger_name, level, message) tuples |
.messages |
list[str] |
Message strings only |
Methods¶
| Method | Description |
|---|---|
set_level(level) |
Set minimum capture level (int or str) |
at_level(level) |
Context manager to temporarily change capture level |
clear() |
Clear all captured records |
capture_logs Context Manager¶
For tests that don't use pytest fixtures, use the capture_logs context manager:
from logxide import logging
from logxide.testing import capture_logs
def test_without_fixture():
logger = logging.getLogger("test")
with capture_logs(logging.INFO) as captured:
logger.addHandler(captured.handler)
logger.info("test message")
assert "test message" in captured.text
MemoryHandler¶
Underneath both LogCaptureFixture and capture_logs, the MemoryHandler stores log records in Rust-native memory:
from logxide import MemoryHandler, logging
logger = logging.getLogger("test")
handler = MemoryHandler()
logger.addHandler(handler)
logger.info("Hello!")
handler.records # [LogRecord(...)]
handler.text # "INFO test Hello!\n"
handler.record_tuples # [("test", 20, "Hello!")]
handler.clear() # Reset for next test
Performance
MemoryHandler stores records in Rust's Vec<LogRecord> behind a Mutex, making it significantly faster than Python-based alternatives for high-volume capture.
Optimization Regression Suite¶
tests/test_optimizations.py is a tracked regression suite that covers the Step 1–4 optimizations shipped in v0.1.19. It runs alongside the standard test suite.
The suite covers:
- Message round-trip verification (Step 1): standard formatting and log round-trips remain correct after removing redundant dynamic message-text caching.
- Tuple-to-array serialization (Step 2):
tuple-valued fields insideglobal_contextorextraserialize to JSON arrays through the unified Python-to-JSON helper. - Direct ANSI color placeholder support (Step 3):
RustFormatter(andFormatter) parse%(ansi_level_color)sand%(ansi_reset_color)sdirectly. - Compat caller-info activation (Step 4): handlers configured through
compat_handlers.pyactivate theactivate_caller_infolayer only when the format references caller-info placeholders such as%(funcName)s.
Run it with: