Skip to content

Capturing, with and without stdlib logging #2079

Closed
@SwampFalc

Description

@SwampFalc

So I find myself rather confused by output capturing.

Let's start by quoting the manual:

def test_myoutput(capsys): # or use "capfd" for fd-level
    print ("hello")
    sys.stderr.write("world\n")
    out, err = capsys.readouterr()
    assert out == "hello\n"
    assert err == "world\n"
    print ("next")
    out, err = capsys.readouterr()
    assert out == "next\n"

I run this with pytest test_me.py and I get a pass.

Then I run this with pytest -s test_me.py, and I still get a pass. Which according to the manual doesn't make sense. -s is described as disabling capturing. So either I'm not grasping something crucial, or the manual is wrong, or there's a bug in the implementation of -s.

I then become even more confused when I try to test the behaviour of the stdlib logging module. I don't mean testing the module, but testing that my app emits the right log entries in the right circumstances.

So I make this example code:

import sys
import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)
handler = logging.StreamHandler(sys.stdout)
logger.addHandler(handler)

def test_myoutput(capsys):
    logger.error('something')
    out, err = capsys.readouterr()
    with capsys.disabled():
        print 'E:' + err
        print 'O:' + out

I run this without -s:

E:
O:

Then I run it with -s:

something
E:
O:

So at first sight this makes some sense. The logging output happens, it just gets captured somewhere, unless I specify -s. So in this case -s does seem to work exactly as described, the only remaining issue is that capsys for some reason doesn't capture what logging emits on sys.stdout...

So we do the obvious next step and replace all occurrences of capsys with capfd!

Run without -s:

E:
O:

Run with -s:

E:
O: something

... What? Without -s the logging output still vanishes into thin air, but now it has actually been captured with -s? So in this case the flag actually turns capturing on, when the description is that it turns capturing off?

Could someone explain what I'm missing here, or what I'm doing wroing?

(I'm aware I could reconfigure my logger so that it goes to a file or something and avoid this, but I'd prefer to stick as closely as possible to my production code)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions