wimglenn / pytest-structlog

Structured logging assertions
MIT License
54 stars 6 forks source link

ScopeMismatch when attempting to use "log" in a module-scoped fixture #9

Closed paravoid closed 4 years ago

paravoid commented 4 years ago

I'm attempting to use the log fixture in another fixture, with the intent to scope it for the whole module (across multiple tests). Unfortunately, this results in a ScopeMismatch ("You tried to access the 'function' scoped fixture 'log' with a 'module' scoped request object, involved factories").

Example code:

import foo  # uses structlog

@pytest.fixture(scope="module")
def foo_instance(log):
    instance = foo.client()  # logs using structlog
    yield instance
wimglenn commented 4 years ago

Yes, pytest-structlog uses a function scoped log fixture, by design. This is so that logs captured in each test were the events produced by the code under test only, i.e. not leaking log events coming from other tests.

Help me to understand why do you want to use the log fixture to be used by a module scoped fixture? What's the use-case here?

paravoid commented 4 years ago

Thanks for the quick response!

I have a socket server, that uses structlog within its body to log various things (new client connected, client A requested X, client B requested Y etc.).

I'd like to run a single instance of this server, then run multiple tests against it. So I created a fixture, scoped to the test module, which initializes the server and returns the instance, so that other tests can use it. This is similar to the smtp_connection fixture listed in the pytest documentation.

Naturally, I'd also like to capture its logs. Among other things, I want to capture a failed initialization, and also to yield the instance from the fixture only after the server has logged that it has successfully initialized and is ready to serve requests.

Does that make sense?

wimglenn commented 4 years ago

Hmm, OK, perhaps you can use structlog's own capturing context manager for that use-case (new in v20.1.0)

from structlog.testing import capture_logs

import foo  # uses structlog

@pytest.fixture(scope="module")
def foo_instance():
    with capture_logs() as events:
        instance = foo.client()
        # block here until instance is initialized and ready, or handle failed init
    yield instance

This way tests can still use the log capture as a function scoped fixture.

wimglenn commented 4 years ago

@paravoid I assume your issue is sorted. If not, feel free to comment/reopen.