Skip to content

Commit

Permalink
Add factory method for log events to assert on for better readability (
Browse files Browse the repository at this point in the history
…#23)

* Add factory method for log events to assert on for better readability

---------

Co-authored-by: Logi <[email protected]>
Co-authored-by: wim glenn <[email protected]>
  • Loading branch information
3 people authored May 4, 2023
1 parent dd4cb70 commit cb82f00
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
9 changes: 9 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ Then your test suite might use assertions such as shown below:
{"event": "processing", "level": "debug", "spline": 2},
{"event": "reticulated splines", "level": "info", "n_splines": 3},
]
# can use friendly factory methods for the events to assert on
assert log.events == [
log.info("reticulating splines"),
log.debug("processing", spline=0),
log.debug("processing", spline=1),
log.debug("processing", spline=2),
log.info("reticulated splines", n_splines=3),
]
# can use membership to check for a single event's data
assert {"event": "reticulating splines", "level": "info"} in log.events
Expand Down
32 changes: 32 additions & 0 deletions pytest_structlog.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import os

import pytest
Expand Down Expand Up @@ -40,6 +41,13 @@ def __lt__(self, other):
absent = object()


def level_to_name(level):
"""Given the name or number for a log-level, return the lower-case level name."""
if isinstance(level, str):
return level.lower()
return logging.getLevelName(level).lower()


def is_submap(d1, d2):
"""is every pair from d1 also in d2? (unique and order insensitive)"""
return all(d2.get(k, absent) == v for k, v in d1.items())
Expand All @@ -64,6 +72,30 @@ def has(self, message, **context):
context["event"] = message
return any(is_submap(context, e) for e in self.events)

def log(self, level, event, **kw):
"""Create log event to assert against"""
return dict(level=level_to_name(level), event=event, **kw)

def debug(self, event, **kw):
"""Create debug-level log event to assert against"""
return self.log(logging.DEBUG, event, **kw)

def info(self, event, **kw):
"""Create info-level log event to assert against"""
return self.log(logging.INFO, event, **kw)

def warning(self, event, **kw):
"""Create warning-level log event to assert against"""
return self.log(logging.WARNING, event, **kw)

def error(self, event, **kw):
"""Create error-level log event to assert against"""
return self.log(logging.ERROR, event, **kw)

def critical(self, event, **kw):
"""Create critical-level log event to assert against"""
return self.log(logging.CRITICAL, event, **kw)


def no_op(*args, **kwargs):
pass
Expand Down
33 changes: 33 additions & 0 deletions tests/test_log.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import logging

import pytest
import structlog


Expand Down Expand Up @@ -140,3 +143,33 @@ def test_dupes(log):
{"event": "a", "level": "info"},
{"event": "b", "level": "info"},
]


def test_event_factories(log):
assert log.debug("debug-level", extra=True) == {"event": "debug-level", "level": "debug", "extra": True}
assert log.info("info-level", more="yes") == {"event": "info-level", "level": "info", "more": "yes"}
assert log.warning("warning-level", another=42) == {"event": "warning-level", "level": "warning", "another": 42}
assert log.error("error-level", added=1) == {"event": "error-level", "level": "error", "added": 1}
assert log.critical("crit-level", above="beyond") == {"event": "crit-level", "level": "critical", "above": "beyond"}


@pytest.mark.parametrize(
"level, name",
[
(logging.DEBUG, "debug"),
(logging.INFO, "info"),
(logging.WARNING, "warning"),
(logging.ERROR, "error"),
(logging.CRITICAL, "critical"),
],
)
def test_dynamic_event_factory(log, level, name):
expected = {"event": "dynamic-level", "level": name, "other": 42}

assert log.log(level, "dynamic-level", other=42) == expected
assert log.log(name, "dynamic-level", other=42) == expected
assert log.log(name.upper(), "dynamic-level", other=42) == expected


def test_event_factory__bad_level_number(log):
assert log.log(1234, "text") == {'event': 'text', 'level': 'level 1234'}

0 comments on commit cb82f00

Please sign in to comment.