I would like to put some logging statements within test function to examine some state variables.
I have the following code snippet:
import pytest,os
import logging
logging.basicConfig(level=logging.DEBUG)
mylogger = logging.getLogger()
#############################################################################
def setup_module(module):
''' Setup for the entire module '''
mylogger.info('Inside Setup')
# Do the actual setup stuff here
pass
def setup_function(func):
''' Setup for test functions '''
if func == test_one:
mylogger.info(' Hurray !!')
def test_one():
''' Test One '''
mylogger.info('Inside Test 1')
#assert 0 == 1
pass
def test_two():
''' Test Two '''
mylogger.info('Inside Test 2')
pass
if __name__ == '__main__':
mylogger.info(' About to start the tests ')
pytest.main(args=[os.path.abspath(__file__)])
mylogger.info(' Done executing the tests ')
I get the following output:
[bmaryada-mbp:/Users/bmaryada/dev/platform/main/proto/tests/tpch $]python minitest.py
INFO:root: About to start the tests
======================================================== test session starts =========================================================
platform darwin -- Python 2.6.2 -- pytest-2.0.0
collected 2 items
minitest.py ..
====================================================== 2 passed in 0.01 seconds ======================================================
INFO:root: Done executing the tests
Notice that only the logging messages from the '__name__ == __main__'
block get transmitted to the console.
Is there a way to force pytest
to emit logging to console from test methods as well?
Since version 3.3, pytest
supports live logging, meaning that all the log records emitted in tests will be printed to the terminal immediately. The feature is documented under Live Logs section. Live logging is disabled by default; to enable it, set log_cli = 1
in the pytest.ini
config1. Live logging supports emitting to terminal and file; the relevant options allow records customizing:
log_cli_level
log_cli_format
log_cli_date_format
log_file
log_file_level
log_file_format
log_file_date_format
Note: As pointed out by Kévin Barré in this comment, overriding ini options from command line can be done via the log_cli
flag can't be passed from command line and must be set in pytest.ini
. All the other options can be both passed from command line or set in the config file.-o/--override
option. So instead of declaring log_cli
in pytest.ini
, you can simply call:
$ pytest -o log_cli=true ...
Simple test file used for demonstrating:
# test_spam.py
import logging
LOGGER = logging.getLogger(__name__)
def test_eggs():
LOGGER.info('eggs info')
LOGGER.warning('eggs warning')
LOGGER.error('eggs error')
LOGGER.critical('eggs critical')
assert True
As you can see, no extra configuration needed; pytest
will setup the logger automatically, based on options specified in pytest.ini
or passed from command line.
INFO
level, fancy outputConfiguration in pytest.ini
:
[pytest]
log_cli = 1
log_cli_level = INFO
log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_cli_date_format=%Y-%m-%d %H:%M:%S
Running the test:
$ pytest test_spam.py
=============================== test session starts ================================
platform darwin -- Python 3.6.4, pytest-3.7.0, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-4673373, inifile: pytest.ini
collected 1 item
test_spam.py::test_eggs
---------------------------------- live log call -----------------------------------
2018-08-01 14:33:20 [ INFO] eggs info (test_spam.py:7)
2018-08-01 14:33:20 [ WARNING] eggs warning (test_spam.py:8)
2018-08-01 14:33:20 [ ERROR] eggs error (test_spam.py:9)
2018-08-01 14:33:20 [CRITICAL] eggs critical (test_spam.py:10)
PASSED [100%]
============================= 1 passed in 0.01 seconds =============================
CRITICAL
level in terminal, fancy output in pytest.log
fileConfiguration in pytest.ini
:
[pytest]
log_cli = 1
log_cli_level = CRITICAL
log_cli_format = %(message)s
log_file = pytest.log
log_file_level = DEBUG
log_file_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
log_file_date_format=%Y-%m-%d %H:%M:%S
Test run:
$ pytest test_spam.py
=============================== test session starts ================================
platform darwin -- Python 3.6.4, pytest-3.7.0, py-1.5.3, pluggy-0.7.1 -- /Users/hoefling/.virtualenvs/stackoverflow/bin/python3.6
cachedir: .pytest_cache
rootdir: /Users/hoefling/projects/private/stackoverflow/so-4673373, inifile: pytest.ini
collected 1 item
test_spam.py::test_eggs
---------------------------------- live log call -----------------------------------
eggs critical
PASSED [100%]
============================= 1 passed in 0.01 seconds =============================
$ cat pytest.log
2018-08-01 14:38:09 [ INFO] eggs info (test_spam.py:7)
2018-08-01 14:38:09 [ WARNING] eggs warning (test_spam.py:8)
2018-08-01 14:38:09 [ ERROR] eggs error (test_spam.py:9)
2018-08-01 14:38:09 [CRITICAL] eggs critical (test_spam.py:10)
1 Although you can configure pytest
in setup.cfg
under the [tool:pytest]
section, don't be tempted to do that when you want to provide custom live logging format. Other tools reading setup.cfg
might treat stuff like %(message)s
as string interpolation and fail. Use pytest.ini
to avoid errors.