Testing logging output with pytest

31,552

Solution 1

I don't know why this didn't work when I tried it before, but this solution works for me now:

In test_module.py:

import logging
from module import run_function

LOGGER = logging.getLogger(__name__)

def test_func(caplog):
    LOGGER.info('Testing now.')
    run_function()
    assert 'Something bad happened!' in caplog.text

Solution 2

test_module.py should look like this:

import logging
from module import run_function

LOGGER = logging.getLogger(__name__)

def test_func(caplog):
    with caplog.at_level(logging.WARNING):
        run_function()
    assert 'Something bad happened!' in caplog.text

or:

import logging
from module import run_function

LOGGER = logging.getLogger(__name__)

def test_func(caplog):
    caplog.set_level(logging.WARNING):
    run_function()
    assert 'Something bad happened!' in caplog.text

Documentation for pytest capture logging is here

Solution 3

In your logging set up, check propagate is set to True, otherwise caplog handler is not able to see the logging message.

Solution 4

I also want to add to this thread for anybody in the future coming across this. You may need to use

@pytest.fixture(autouse=True)

as a decorator on your test so the test has access to the caplog fixture.

Share:
31,552
lauren.marietta
Author by

lauren.marietta

Updated on November 12, 2021

Comments

  • lauren.marietta
    lauren.marietta over 2 years

    I am trying to write a test, using pytest, that would check that a specific function is writing out a warning to the log when needed. For example:

    In module.py:

    import logging
    LOGGER = logging.getLogger(__name__)
    
    def run_function():
        if something_bad_happens:
            LOGGER.warning('Something bad happened!')
    

    In test_module.py:

    import logging
    from module import run_function
    
    LOGGER = logging.getLogger(__name__)
    
    def test_func():
        LOGGER.info('Testing now.')
        run_function()
        ~ somehow get the stdout/log of run_function() ~
        assert 'Something bad happened!' in output
    

    I have seen that you can supposedly get the log or the stdout/stderr with pytest by passing capsys or caplog as an argument to the test, and then using either capsus.readouterr() or caplog.records to access the output.

    However, when I try those methods, I only see "Testing now.", and not "Something bad happened!". It seems like the logging output that is happening within the call to run_function() is not accessible from test_func()?

    The same thing happens if I try a more direct method, such as sys.stdout.getvalue(). Which is confusing, because run_function() is writing to the terminal, so I would think that would be accessible from stdout...?

    Basically, does anyone know how I can access that 'Something bad happened!' from within test_func()?