Testing Log Output#
FastCS uses loguru for logging. The test suite provides
a loguru_caplog fixture that bridges loguru into pytest’s standard caplog mechanism,
making it straightforward to assert on log messages in tests.
The loguru_caplog Fixture#
The fixture is defined in tests/conftest.py and registers a loguru sink that forwards
all messages (down to TRACE level) into pytest’s caplog:
@pytest.fixture
def loguru_caplog(caplog):
handler_id = logger.add(caplog.handler, format="{message}", level="TRACE")
yield caplog
logger.remove(handler_id)
Use it by adding loguru_caplog as a parameter to your test function. The yielded value
is pytest’s standard caplog object, so the same assertions work:
loguru_caplog.text— all captured log output as a single stringloguru_caplog.records— list oflogging.LogRecordobjects, each with a.messageattribute
Asserting on ERROR-level Messages#
Pass loguru_caplog to any test that exercises code that calls logger.error(...) or
similar. After the code runs, assert against loguru_caplog.text:
@pytest.mark.asyncio
async def test_attr_r_update_logs_validation_error(loguru_caplog):
attr = AttrR(Int())
with pytest.raises(ValueError):
await attr.update("not_an_int")
assert "Failed to validate value" in loguru_caplog.text
The same pattern applies when a callback raises:
@pytest.mark.asyncio
async def test_attr_r_update_logs_callback_failure(loguru_caplog):
attr = AttrR(Int())
async def failing_callback(_value: int):
raise RuntimeError("callback failed")
attr.add_on_update_callback(failing_callback)
with pytest.raises(RuntimeError):
await attr.update(42)
assert "On update callbacks failed" in loguru_caplog.text
Asserting on TRACE-level Messages#
log_event calls (from the Tracer mixin) emit at TRACE level and are only active
when tracing is enabled on that object. The loguru_caplog fixture captures at TRACE
level, so no extra setup is needed beyond enabling tracing on the object under test.
Use loguru_caplog.records and check .message on each record for precise matching:
@pytest.mark.asyncio
async def test_attr_r_update_trace_logs_when_tracing_enabled(loguru_caplog):
"""log_event emits 'Attribute set' and 'Value validated' when tracing is on."""
attr = AttrR(Int())
attr.enable_tracing()
await attr.update(42)
messages = [r.message for r in loguru_caplog.records]
assert any("Attribute set" in m for m in messages)
assert any("Value validated" in m for m in messages)
You can also verify that messages are absent when tracing is not enabled:
@pytest.mark.asyncio
async def test_attr_r_update_no_trace_logs_when_tracing_disabled(loguru_caplog):
attr = AttrR(Int())
await attr.update(42)
messages = [r.message for r in loguru_caplog.records]
assert not any("Attribute set" in m for m in messages)
assert not any("Value validated" in m for m in messages)