Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add call recorder for testing purposes #14

Closed
hynek opened this issue Nov 10, 2013 · 8 comments
Closed

Add call recorder for testing purposes #14

hynek opened this issue Nov 10, 2013 · 8 comments

Comments

@hynek
Copy link
Owner

@hynek hynek commented Nov 10, 2013

Basically a processor that records all calls and allows assertions against it. Needs #10.

@hynek hynek removed this from the 0.5.0 milestone Jul 29, 2014
@hynek hynek added this to the 14.0.0 milestone Jul 29, 2014
@hynek hynek removed this from the 15.0.0 milestone Jan 15, 2015
@hynek hynek added this to the 15.1.0 milestone Jan 15, 2015
@hynek hynek added this to the 15.1.0 milestone Jan 15, 2015
@hynek hynek removed this from the 15.0.0 milestone Jan 15, 2015
@hynek hynek removed this from the 16.1.0 milestone Apr 24, 2017
@aldanor
Copy link

@aldanor aldanor commented Jul 19, 2018

This is a super old issue, but still -- wondering if there's a 'recommended' way of testing structlog loggers these days?.. (which isn't entirely clear from docs or issues, hence the question)

@aldanor
Copy link

@aldanor aldanor commented Jul 19, 2018

Here's what I'm usually doing in pytest:

class LogCapture:
    def __init__(self):
        self.entries = []

    def __call__(self, _, method_name, event_dict):
        event_dict['log_level'] = method_name
        self.entries.append(event_dict)
        raise structlog.DropEvent


@pytest.fixture(scope='function')
def log_output():
    return LogCapture()


@pytest.fixture(scope='function', autouse=True)
def configure_structlog(log_output):
    structlog.configure(
        processors=[log_output]
    )

and then you can just

def test_my_stuff(log_output):
    do_something()
    assert log_output.entries == [...]

@hynek
Copy link
Owner Author

@hynek hynek commented Jul 21, 2018

Honestly that’s pretty much I had in mind but never got around to implement it in a way that it would warrant the inclusion in structlog proper. Lately I've also been kinda lazy and just used caplog/capsys + simples checks to ensure an entry is in there. 🤔

@rgalanakis
Copy link
Contributor

@rgalanakis rgalanakis commented Dec 9, 2019

Here's a non-pytest version, in case anyone comes across this and needs it:

class LogCapture:
    def __init__(self):
        self.entries = []

    def __call__(self, _, method_name, event_dict):
        event_dict['log_level'] = method_name
        self.entries.append(event_dict)
        raise structlog.DropEvent


@contextmanager
def capture_logs():
    cap = LogCapture()
    old_processors = structlog.get_config()['processors']
    try:
        structlog.configure(processors=[cap])
        yield cap.entries
    finally:
        structlog.configure(processors=old_processors)

Yield value looks something like: [{'error': ClientError('An error occurred (404) when calling the HeadObject operation: Not Found',), 'event': 'download_csv_error', 'log_level': 'critical'}]

@hynek
Copy link
Owner Author

@hynek hynek commented Dec 10, 2019

@rgalanakis wow I love that approach! Simple yet powerful! I think I wouldn't be opposed to adding that to structlog proper!

@rgalanakis
Copy link
Contributor

@rgalanakis rgalanakis commented Dec 10, 2019

Great and thanks! Do you want a PR or will you add it yourself?

@hynek
Copy link
Owner Author

@hynek hynek commented Dec 11, 2019

I would like you to have the implementation credit but it will take a bit more than just the code. 🤔 I guess a Testing chapter is in order?

rgalanakis added a commit to rgalanakis/structlog that referenced this issue Dec 12, 2019
See hynek#14 (comment)
for more context.

It needed to go into its own file, rather than `dev`,
because it relies on `_config` and `_config` relies on `dev`.
rgalanakis added a commit to rgalanakis/structlog that referenced this issue Dec 12, 2019
See hynek#14 (comment)
for more context.

It needed to go into its own file, rather than `dev`,
because it relies on `_config` and `_config` relies on `dev`.
rgalanakis added a commit to rgalanakis/structlog that referenced this issue Dec 12, 2019
See hynek#14 (comment)
for more context.

It needed to go into its own file, rather than `dev`,
because it relies on `_config` and `_config` relies on `dev`.
rgalanakis added a commit to rgalanakis/structlog that referenced this issue Dec 12, 2019
See hynek#14 (comment)
for more context.

It needed to go into its own file, rather than `dev`,
because it relies on `_config` and `_config` relies on `dev`.
rgalanakis added a commit to rgalanakis/structlog that referenced this issue Dec 12, 2019
See hynek#14 (comment)
for more context.

It needed to go into its own file, rather than `dev`,
because it relies on `_config` and `_config` relies on `dev`.
hynek added a commit that referenced this issue Jan 6, 2020
* Add capture_logs context manager

See #14 (comment)
for more context.

It needed to go into its own file, rather than `dev`,
because it relies on `_config` and `_config` relies on `dev`.

* Rename _capture.py to testing.py

* Add docstring to testing.LogCapture

Co-authored-by: Hynek Schlawack <hs@ox.cx>
@hynek
Copy link
Owner Author

@hynek hynek commented Jan 6, 2020

Finally fixed by #234! 🎉

@hynek hynek closed this Jan 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants