LoggingPlugin: Expose setting log_file_handler
- This patch allows to set log_file (path) from hook Signed-off-by: Thomas Hisch Signed-off-by: Andras Mitzki <andras.mitzki@balabit.com>
This commit is contained in:
parent
a131cd6c3b
commit
e3824d23bc
1
AUTHORS
1
AUTHORS
|
@ -16,6 +16,7 @@ Allan Feldman
|
|||
Aly Sivji
|
||||
Anatoly Bubenkoff
|
||||
Anders Hovmöller
|
||||
Andras Mitzki
|
||||
Andras Tim
|
||||
Andrea Cimatoribus
|
||||
Andreas Zeidler
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
With the help of new ``set_log_path()`` method there is a way to set ``log_file`` paths from hooks.
|
|
@ -198,6 +198,9 @@ option names are:
|
|||
* ``log_file_format``
|
||||
* ``log_file_date_format``
|
||||
|
||||
You can call ``set_log_path()`` to customize the log_file path dynamically. This functionality
|
||||
is considered **experimental**.
|
||||
|
||||
.. _log_release_notes:
|
||||
|
||||
Release notes
|
||||
|
|
|
@ -13,6 +13,7 @@ import six
|
|||
import pytest
|
||||
from _pytest.compat import dummy_context_manager
|
||||
from _pytest.config import create_terminal_writer
|
||||
from _pytest.pathlib import Path
|
||||
|
||||
|
||||
DEFAULT_LOG_FORMAT = "%(filename)-25s %(lineno)4d %(levelname)-8s %(message)s"
|
||||
|
@ -399,22 +400,21 @@ class LoggingPlugin(object):
|
|||
)
|
||||
self.log_level = get_actual_log_level(config, "log_level")
|
||||
|
||||
self.log_file_level = get_actual_log_level(config, "log_file_level")
|
||||
self.log_file_format = get_option_ini(config, "log_file_format", "log_format")
|
||||
self.log_file_date_format = get_option_ini(
|
||||
config, "log_file_date_format", "log_date_format"
|
||||
)
|
||||
self.log_file_formatter = logging.Formatter(
|
||||
self.log_file_format, datefmt=self.log_file_date_format
|
||||
)
|
||||
|
||||
log_file = get_option_ini(config, "log_file")
|
||||
if log_file:
|
||||
self.log_file_level = get_actual_log_level(config, "log_file_level")
|
||||
|
||||
log_file_format = get_option_ini(config, "log_file_format", "log_format")
|
||||
log_file_date_format = get_option_ini(
|
||||
config, "log_file_date_format", "log_date_format"
|
||||
)
|
||||
# Each pytest runtests session will write to a clean logfile
|
||||
self.log_file_handler = logging.FileHandler(
|
||||
log_file, mode="w", encoding="UTF-8"
|
||||
)
|
||||
log_file_formatter = logging.Formatter(
|
||||
log_file_format, datefmt=log_file_date_format
|
||||
)
|
||||
self.log_file_handler.setFormatter(log_file_formatter)
|
||||
self.log_file_handler.setFormatter(self.log_file_formatter)
|
||||
else:
|
||||
self.log_file_handler = None
|
||||
|
||||
|
@ -468,6 +468,27 @@ class LoggingPlugin(object):
|
|||
log_cli_handler, formatter=log_cli_formatter, level=log_cli_level
|
||||
)
|
||||
|
||||
def set_log_path(self, fname):
|
||||
"""Public method, which can set filename parameter for
|
||||
Logging.FileHandler(). Also creates parent directory if
|
||||
it does not exist.
|
||||
|
||||
.. warning::
|
||||
Please considered as an experimental API.
|
||||
"""
|
||||
fname = Path(fname)
|
||||
|
||||
if not fname.is_absolute():
|
||||
fname = Path(self._config.rootdir, fname)
|
||||
|
||||
if not fname.parent.exists():
|
||||
fname.parent.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
self.log_file_handler = logging.FileHandler(
|
||||
str(fname), mode="w", encoding="UTF-8"
|
||||
)
|
||||
self.log_file_handler.setFormatter(self.log_file_formatter)
|
||||
|
||||
def _log_cli_enabled(self):
|
||||
"""Return True if log_cli should be considered enabled, either explicitly
|
||||
or because --log-cli-level was given in the command-line.
|
||||
|
@ -490,6 +511,15 @@ class LoggingPlugin(object):
|
|||
|
||||
@contextmanager
|
||||
def _runtest_for(self, item, when):
|
||||
with self._runtest_for_main(item, when):
|
||||
if self.log_file_handler is not None:
|
||||
with catching_logs(self.log_file_handler, level=self.log_file_level):
|
||||
yield
|
||||
else:
|
||||
yield
|
||||
|
||||
@contextmanager
|
||||
def _runtest_for_main(self, item, when):
|
||||
"""Implements the internals of pytest_runtest_xxx() hook."""
|
||||
with catching_logs(
|
||||
LogCaptureHandler(), formatter=self.formatter, level=self.log_level
|
||||
|
|
|
@ -1002,3 +1002,51 @@ def test_log_in_hooks(testdir):
|
|||
assert "sessionstart" in contents
|
||||
assert "runtestloop" in contents
|
||||
assert "sessionfinish" in contents
|
||||
|
||||
|
||||
def test_log_set_path(testdir):
|
||||
report_dir_base = testdir.tmpdir.strpath
|
||||
|
||||
testdir.makeini(
|
||||
"""
|
||||
[pytest]
|
||||
log_file_level = DEBUG
|
||||
log_cli=true
|
||||
"""
|
||||
)
|
||||
testdir.makeconftest(
|
||||
"""
|
||||
import os
|
||||
import pytest
|
||||
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
|
||||
def pytest_runtest_setup(item):
|
||||
config = item.config
|
||||
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
|
||||
report_file = os.path.join({}, item._request.node.name)
|
||||
logging_plugin.set_log_path(report_file)
|
||||
yield
|
||||
""".format(
|
||||
repr(report_dir_base)
|
||||
)
|
||||
)
|
||||
testdir.makepyfile(
|
||||
"""
|
||||
import logging
|
||||
logger = logging.getLogger("testcase-logger")
|
||||
def test_first():
|
||||
logger.info("message from test 1")
|
||||
assert True
|
||||
|
||||
def test_second():
|
||||
logger.debug("message from test 2")
|
||||
assert True
|
||||
"""
|
||||
)
|
||||
testdir.runpytest()
|
||||
with open(os.path.join(report_dir_base, "test_first"), "r") as rfh:
|
||||
content = rfh.read()
|
||||
assert "message from test 1" in content
|
||||
|
||||
with open(os.path.join(report_dir_base, "test_second"), "r") as rfh:
|
||||
content = rfh.read()
|
||||
assert "message from test 2" in content
|
||||
|
|
Loading…
Reference in New Issue