Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use logging, pytest fixture and capsys?

I am trying to unit-test some algorithm that uses logging library.

I have a fixture that creates a logger.

In my 1st test case, I do not use this fixture and uses a print to log to stdout. This test case passes.

In my 2nd test case, I use this fixture, but not as documented in pytest doc. I just call the associated function in my test to get the logger. Then I use the logger to log to stdout. This test case passes.

In my 3rd test case, I use this fixture as documented in pytest doc. The fixture is passed as an argument to the test function. Then I use the logger to log to stdout. This test case fails! It does not find anything in stdout. But in the error message, it says that my log is in the captured stdout call.

What am I doing wrong?

import pytest

import logging
import sys

@pytest.fixture()
def logger():

    logger = logging.getLogger('Some.Logger')
    logger.setLevel(logging.INFO)
    stdout = logging.StreamHandler(sys.stdout)
    logger.addHandler(stdout)

    return logger

def test_print(capsys):

    print 'Bouyaka!'

    stdout, stderr = capsys.readouterr()
    assert 'Bouyaka!' in stdout

    # passes

def test_logger_without_fixture(capsys):

    logger().info('Bouyaka!')

    stdout, stderr = capsys.readouterr()
    assert 'Bouyaka!' in stdout

    # passes

def test_logger_with_fixture(logger, capsys):

    logger.info('Bouyaka!')

    stdout, stderr = capsys.readouterr()
    assert 'Bouyaka!' in stdout

    # fails with this error:
    # >       assert 'Bouyaka!' in stdout
    # E       assert 'Bouyaka!' in ''
    #
    # tests/test_logging.py:21: AssertionError
    # ---- Captured stdout call ----
    # Bouyaka!

There is no change if I reorder the test cases by the way.

like image 793
MickaelM Avatar asked Jul 26 '16 15:07

MickaelM


People also ask

What is logging in pytest?

pytest captures log messages of level WARNING or above automatically and displays them in their own section for each failed test in the same manner as captured stdout and stderr.

How do I use pytest fixtures?

To access the fixture function, the tests have to mention the fixture name as input parameter. Pytest while the test is getting executed, will see the fixture name as input parameter. It then executes the fixture function and the returned value is stored to the input parameter, which can be used by the test.

Does pytest disable logging?

Pytest does not support this by default, but you can add a custom option to your conftest.py to turn off specific loggers.

Which fixture is instantiated first?

Higher-scoped fixtures are instantiated first¶ Within a function request for features, fixture of higher-scopes (such as session ) are instantiated first than lower-scoped fixtures (such as function or class ).


1 Answers

As of pytest 3.3, the functionality of capturing log message was added to pytest core. This is supported by the caplog fixture:

def test_baz(caplog):
    func_under_test()
    for record in caplog.records:
        assert record.levelname != 'CRITICAL'
    assert 'wally' not in caplog.text

More information can be found at the documentation

like image 126
Cesar Canassa Avatar answered Oct 20 '22 09:10

Cesar Canassa