Skip to main content
  1. Posts/

Logging setup for Pytest

·394 words·2 mins·
Python Pytest
Table of Contents

When you do code testing using pytest, pytest can do sophisticated changes to your logging. This is a very powerful feature, but carries some subtlety.

log_cli and log_cli_level
#

Suppose that we have the following test case:


import logging
logger = logging.getLogger()

def test_something():
    logger.debug("Debug message")
    logger.info("Info message")
    logger.warning("Warn message")
    logger.error("Error message")

    assert True

[log_cli][pytest-option-log-cli] can control whether to enable live log on cli. Note that this option does not have a command line equivalent (i.e., it can only be set in config file) We can use option log_cli_level (or --log-cli-level on cli) to control the logging printed on command line.

If we have the following pytest config (use pytest.ini):

[pytest]
log_cli = true
log_cli_level = WARN

If you run pytest, you will see that only WARN and Error logging is shown on cli. If you have log_cli_level = INFO, you see INFO, WARN and ERROR logging. So under the hood, it seems log_cli_level will also set your root logger level1.

log_cli_level vs log_level
#

There is another option log_level that controls the log level of root logger. Based on experiments, log_level has priority over log_cli_level in setting the root logger. This is easy to verify. We change the test case a bit:

import logging
logger = logging.getLogger()

def test_something():
    foo = 123
    logger.debug("Debug message")
    logger.info("Info message %", foo)
    logger.warning("Warn message")
    logger.error("Error message")

    assert True

The INFO logging is ill-formatted and will error out if it is run. We use the following pytest config:


[pytest]
log_cli = true
log_cli_level = WARN
log_level = INFO

If you run pytest, you will see format errors:

ValueError: incomplete format

You will not see error if you use this config (logging is only initialized starting with WARN level):

[pytest]
log_cli = true
log_cli_level = INFO
log_level = WARN

caplog fixture
#

There is another level of complication. If you use caplog.set_level() fixture inside test, it can also change the logging level. Now we change our test case to the following:

import logging
logger = logging.getLogger()

def test_something(caplog):
    caplog.set_level(logging.WARN)

    foo = 123
    logger.debug("Debug message")
    logger.info("Info message %", foo)
    logger.warning("Warn message")
    logger.error("Error message")

    assert True

On the command line, if you run pytest --log-cli-level=INFO, the test is still going to pass: caplog.set_level has silently override the logging level you set via --log-cli-level. The effect of caplog.set_level make is only in this test only.


  1. The default root logger level is WARN ↩︎

Related

Python system PATH issues When We Use Pytest
·461 words·3 mins
Python Pytest
How to Filter Warnings in Python/pytest
··404 words·2 mins
Python Pytest
Run the Job Immediately after Starting Scheduler in Python APScheduler
··323 words·2 mins
Python APScheduler