Skip to content

Can't capture output of logger in stdout #13402

@MarcBresson

Description

@MarcBresson

Likely a duplicate of #9361 and #10486

I'm trying to assert the behaviour of a context manager that alters a specific logger. For that I was trying to capture the stdout and see if the log message was in it. However, I did not work as expected. The capsys fixture doesn't capture the log output, despite it being logged in the test failure summary.

Minimal reproducible example

import logging
import sys

formatter = logging.Formatter("%(message)s")
stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setFormatter(formatter)
logger = logging.getLogger("test")


def set_verbose(verbose: bool):
    if verbose:
        logger.setLevel(logging.DEBUG)
        logger.removeHandler(stdout_handler)
        logger.addHandler(stdout_handler)
    else:
        logger.setLevel(logging.CRITICAL)
        logger.removeHandler(stdout_handler)


# passes
def test_set_verbose_log(caplog):
    set_verbose(True)
    logger.info("test-2-")
    assert "test-2-" in caplog.text

    set_verbose(False)
    logger.info("test-3-")
    assert "test-3-" not in caplog.text

    set_verbose(True)
    logger.info("test-4-")
    assert "test-4-" in caplog.text

    set_verbose(False)
    logger.info("test-5-")
    assert "test-5-" not in caplog.text


# fails
def test_set_verbose_sys(capsys):
    set_verbose(True)
    logger.info("test-6-")
    assert "test-6-" in capsys.readouterr().out

    set_verbose(False)
    logger.info("test-7-")
    assert "test-7-" not in capsys.readouterr().out

    set_verbose(True)
    logger.info("test-8-")
    assert "test-8-" in capsys.readouterr().out

    set_verbose(False)
    logger.info("test-9-")
    assert "test-9-" in capsys.readouterr().out


# fails when ran with `pytest` but passes when ran with `pytest --capture=tee-sys`
def test_set_verbose_fd(capfd):
    set_verbose(True)
    logger.info("test-10-")
    assert "test-10-" in capfd.readouterr().out

    set_verbose(False)
    logger.info("test-11-")
    assert "test-11-" not in capfd.readouterr().out

Running this with pytest will output the following, which shows "Captured stdout call".

====================================================================== FAILURES ======================================================================
________________________________________________________________ test_set_verbose_sys ________________________________________________________________

capsys = <_pytest.capture.CaptureFixture object at 0x107dff250>

    def test_set_verbose_sys(capsys):
        set_verbose(True)
        logger.info("test-6-")
>       assert "test-6-" in capsys.readouterr().out
E       AssertionError: assert 'test-6-' in ''
E        +  where '' = CaptureResult(out='', err='').out
E        +    where CaptureResult(out='', err='') = readouterr()
E        +      where readouterr = <_pytest.capture.CaptureFixture object at 0x107dff250>.readouterr

tests/test_test.py:43: AssertionError
---------------------------------------------------------------- Captured stdout call ----------------------------------------------------------------
test-6-
----------------------------------------------------------------- Captured log call ------------------------------------------------------------------
INFO     test:test_test.py:42 test-6-
________________________________________________________________ test_set_verbose_fd _________________________________________________________________

capfd = <_pytest.capture.CaptureFixture object at 0x10b6dc190>

    def test_set_verbose_fd(capfd):
        set_verbose(True)
        logger.info("test-10-")
>       assert "test-10-" in capfd.readouterr().out
E       AssertionError: assert 'test-10-' in ''
E        +  where '' = CaptureResult(out='', err='').out
E        +    where CaptureResult(out='', err='') = readouterr()
E        +      where readouterr = <_pytest.capture.CaptureFixture object at 0x10b6dc190>.readouterr

tests/test_test.py:62: AssertionError
---------------------------------------------------------------- Captured stdout call ----------------------------------------------------------------
test-10-
----------------------------------------------------------------- Captured log call ------------------------------------------------------------------
INFO     test:test_test.py:61 test-10-
============================================================== short test summary info ===============================================================
FAILED tests/test_test.py::test_set_verbose_sys - AssertionError: assert 'test-6-' in ''
FAILED tests/test_test.py::test_set_verbose_fd - AssertionError: assert 'test-10-' in ''

Pytest version

platform darwin -- Python 3.13.2, pytest-8.3.4, pluggy-1.5.0
rootdir: /Users/datategy/Documents/papai-unified-storage
configfile: pyproject.toml
plugins: cov-6.0.0, mock-3.14.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    plugin: capturerelated to the capture builtin pluginplugin: loggingrelated to the logging builtin plugin

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions