Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

logging disabled when used with pytest

I am having a problem when using pytest and logging together. When I run a program on its own, I can see its messages printed on screen as well as in the file test.log.

python3 main.py -> prints on terminal, and also in test.log

However, when I am running the same program with pytest, I am seeing the messages only on screen, but the file test.log is not being created.

pytest -vs test -> prints only on terminal, but not in test.log

Why is pytest interfering with the logging utility, and what should I do to create these log files when using pytest?

My versions are the following:

platform linux -- Python 3.6.7, pytest-4.0.2, py-1.7.0, pluggy-0.8.0 -- /usr/bin/python3

The directory structure is the following:

├── logger.py
├── main.py
└── test
    ├── __init__.py
    └── test_module01.py

The code for these files are given below:

# logger.py ===================================
import logging

def logconfig(logfile, loglevel):
    print('logconfig: logfile={} loglevel={}..'.format(logfile,loglevel))
    logging.basicConfig(filename=logfile, level=logging.INFO, format='%(asctime)s :: %(message)s')

def logmsg(log_level, msg):
    print(log_level,': ',msg)
    logging.info('INFO: ' + msg)

# main.py =====================================
from datetime import datetime
from logger import *

def main(BASE_DIR):
    LOG_FILE = BASE_DIR + 'test.log'
    logconfig(LOG_FILE,'INFO')
    logmsg('INFO',"Starting PROGRAM@[{}] at {}=".format(BASE_DIR,datetime.now()))
    logmsg('INFO',"Ending PROGRAM at {}=".format(datetime.now()))

if __name__ == "__main__":
    main('./')

# __init__.py =================================
all = ["test_module01"]

# test_module01.py ============================
import pytest
import main

class TestClass01:
    def test_case01(self):
        print("In test_case01()")
        main.main('./test/')
like image 583
R71 Avatar asked Jan 08 '19 13:01

R71


People also ask

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.

How to enable logging in pytest?

By setting the log_cli configuration option to true , pytest will output logging records as they are emitted directly into the console. You can specify the logging level for which log records with equal or higher level are printed to the console by passing --log-cli-level .


1 Answers

By default, pytest captures all log records emitted by your program. This means that all logging handlers defined in your code will be replaced with the custom handler pytest uses internally; if you pass -s, it will print the emitted records to the terminal, otherwise it will print nothing and no further output is being made. The internal handler will capture all records emitted from your code. To access them in the tests, use the caplog fixture. Example: imagine you need to test the following program:

import logging
import time


def spam():
    logging.basicConfig(level=logging.CRITICAL)
    logging.debug('spam starts')
    time.sleep(1)
    logging.critical('Oopsie')
    logging.debug('spam ends')


if __name__ == '__main__':
    spam()

If you run the program, you'll see the output

CRITICAL:root:Oopsie

but there's no obvious way to access the debug messages. No problem when using caplog:

def test_spam(caplog):
    with caplog.at_level(logging.DEBUG):
        spam()
    assert len(caplog.records) == 3
    assert caplog.records[0].message == 'spam starts'
    assert caplog.records[-1].message == 'spam ends'

If you don't need log capturing (for example, when writing system tests with pytest), you can turn it off by disabling the logging plugin:

$ pytest -p no:logging

Or persist it in the pytest.cfg to not having to enter it each time:

[pytest]
addopts = -p no:logging

Of course, once the log capturing is explicitly disabled, you can't rely on caplog anymore.

like image 126
hoefling Avatar answered Nov 15 '22 09:11

hoefling