Skip to content

CliRunner.invoke doesn't capture stdout from logging #2497

@Kamforka

Description

@Kamforka

The result of CliRunner().invoke doesn't capture stdout logs from logging loggers.

Example:

# capture.py
import logging
import sys

import click
from click.testing import CliRunner


def test_output():
    handler = logging.StreamHandler(sys.stdout)
    logger = logging.getLogger("default")
    logger.addHandler(handler)
    logger.setLevel(logging.INFO)
    sample_log = "Info log from the default logger."

    @click.command()
    def cli():
        logger.info(sample_log)

    runner = CliRunner()
    result = runner.invoke(cli)
    assert result.exit_code == 0
    assert result.output == sample_log

Then to verify that the capture doesn't work:

$ pytest capture.py -vv
======================================================== test session starts ========================================================
platform linux -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0 -- <...>/venv/bin/python
cachedir: .pytest_cache
rootdir: <...>
collected 1 item                                                                                                                    

capture.py::test_output FAILED                                                                                                [100%]

============================================================= FAILURES ==============================================================
____________________________________________________________ test_output ____________________________________________________________

    def test_output():
        handler = logging.StreamHandler(sys.stdout)
        logger = logging.getLogger("default")
        logger.addHandler(handler)
        logger.setLevel(logging.INFO)
        sample_log = "Info log from the default logger."
    
        @click.command()
        def cli():
            logger.info(sample_log)
    
        runner = CliRunner()
        result = runner.invoke(cli)
        assert result.exit_code == 0
>       assert result.output == sample_log
E       AssertionError: assert '' == 'Info log from the default logger.'
E         - Info log from the default logger.

capture.py:22: AssertionError
------------------------------------------------------- Captured stdout call --------------------------------------------------------
Info log from the default logger.
--------------------------------------------------------- Captured log call ---------------------------------------------------------
INFO     default:capture.py:17 Info log from the default logger.
====================================================== short test summary info ======================================================
FAILED capture.py::test_output - AssertionError: assert '' == 'Info log from the default logger.'
========================================================= 1 failed in 0.10s =========================================================

From the above one can see that the content of result.output is an empty string, but judging from the stdout content captured by the test it should be "Info log from the default logger.".

Environment:

  • Python version: 3.11.2
  • Click version: 8.0.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions