Skip to content

Commit

Permalink
Live log option now writes to the terminal reporter
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoddemus committed Jan 20, 2018
1 parent aca1b06 commit 8d735f3
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 33 deletions.
45 changes: 26 additions & 19 deletions _pytest/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import logging
from contextlib import closing, contextmanager
import sys
import six

import pytest
Expand Down Expand Up @@ -270,30 +269,13 @@ def __init__(self, config):
The formatter can be safely shared across all handlers so
create a single one for the entire test session here.
"""
self._config = config
self.print_logs = get_option_ini(config, 'log_print')
self.formatter = logging.Formatter(
get_option_ini(config, 'log_format'),
get_option_ini(config, 'log_date_format'))
self.log_level = get_actual_log_level(config, 'log_level')

if config.getini('log_cli'):
log_cli_handler = logging.StreamHandler(sys.stderr)
log_cli_format = get_option_ini(
config, 'log_cli_format', 'log_format')
log_cli_date_format = get_option_ini(
config, 'log_cli_date_format', 'log_date_format')
log_cli_formatter = logging.Formatter(
log_cli_format,
datefmt=log_cli_date_format)
log_cli_level = get_actual_log_level(config, 'log_cli_level', 'log_level')
self.log_cli_handler = log_cli_handler # needed for a single unittest
self.live_logs_context = catching_logs(log_cli_handler,
formatter=log_cli_formatter,
level=log_cli_level)
else:
self.log_cli_handler = None
self.live_logs_context = _dummy_context_manager()

log_file = get_option_ini(config, 'log_file')
if log_file:
self.log_file_level = get_actual_log_level(config, 'log_file_level')
Expand Down Expand Up @@ -352,6 +334,7 @@ def pytest_runtest_teardown(self, item):
@pytest.hookimpl(hookwrapper=True)
def pytest_runtestloop(self, session):
"""Runs all collected test items."""
self._setup_cli_logging()
with self.live_logs_context:
if self.log_file_handler is not None:
with closing(self.log_file_handler):
Expand All @@ -360,3 +343,27 @@ def pytest_runtestloop(self, session):
yield # run all the tests
else:
yield # run all the tests

def _setup_cli_logging(self):
"""Setups the handler and logger for the Live Logs feature, if enabled.
This must be done right before starting the loop so we can access the terminal reporter plugin.
"""
terminal_reporter = self._config.pluginmanager.get_plugin('terminalreporter')
if self._config.getini('log_cli') and terminal_reporter is not None:
log_cli_handler = logging.StreamHandler(terminal_reporter._tw)
log_cli_format = get_option_ini(
self._config, 'log_cli_format', 'log_format')
log_cli_date_format = get_option_ini(
self._config, 'log_cli_date_format', 'log_date_format')
log_cli_formatter = logging.Formatter(
log_cli_format,
datefmt=log_cli_date_format)
log_cli_level = get_actual_log_level(self._config, 'log_cli_level', 'log_level')
self.log_cli_handler = log_cli_handler # needed for a single unittest
self.live_logs_context = catching_logs(log_cli_handler,
formatter=log_cli_formatter,
level=log_cli_level)
else:
self.log_cli_handler = None
self.live_logs_context = _dummy_context_manager()
32 changes: 18 additions & 14 deletions testing/logging/test_reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,9 @@ def test_log_cli():
''')
result = testdir.runpytest('-s')
if enabled:
assert msg in result.stderr.str()
assert msg in result.stdout.str()
else:
assert msg not in result.stderr.str()
assert msg not in result.stdout.str()


def test_log_cli_default_level(testdir):
Expand All @@ -182,12 +182,13 @@ def test_log_cli(request):

# fnmatch_lines does an assertion internally
result.stdout.fnmatch_lines([
'test_log_cli_default_level.py PASSED',
'test_log_cli_default_level.py*',
'PASSED', # 'PASSED' on its own line because the log message prints a new line
])
result.stderr.fnmatch_lines([
result.stdout.fnmatch_lines([
'*WARNING message will be shown*',
])
assert "INFO message won't be shown" not in result.stderr.str()
assert "INFO message won't be shown" not in result.stdout.str()
# make sure that that we get a '0' exit code for the testsuite
assert result.ret == 0

Expand All @@ -213,12 +214,13 @@ def test_log_cli(request):

# fnmatch_lines does an assertion internally
result.stdout.fnmatch_lines([
'test_log_cli_level.py PASSED',
'test_log_cli_level.py*',
'PASSED', # 'PASSED' on its own line because the log message prints a new line
])
result.stderr.fnmatch_lines([
result.stdout.fnmatch_lines([
"* This log message will be shown"
])
for line in result.errlines:
for line in result.outlines:
try:
assert "This log message won't be shown" in line
pytest.fail("A log message was shown and it shouldn't have been")
Expand All @@ -232,12 +234,13 @@ def test_log_cli(request):

# fnmatch_lines does an assertion internally
result.stdout.fnmatch_lines([
'test_log_cli_level.py PASSED',
'test_log_cli_level.py*',
'PASSED', # 'PASSED' on its own line because the log message prints a new line
])
result.stderr.fnmatch_lines([
result.stdout.fnmatch_lines([
"* This log message will be shown"
])
for line in result.errlines:
for line in result.outlines:
try:
assert "This log message won't be shown" in line
pytest.fail("A log message was shown and it shouldn't have been")
Expand Down Expand Up @@ -270,12 +273,13 @@ def test_log_cli(request):

# fnmatch_lines does an assertion internally
result.stdout.fnmatch_lines([
'test_log_cli_ini_level.py PASSED',
'test_log_cli_ini_level.py*',
'PASSED', # 'PASSED' on its own line because the log message prints a new line
])
result.stderr.fnmatch_lines([
result.stdout.fnmatch_lines([
"* This log message will be shown"
])
for line in result.errlines:
for line in result.outlines:
try:
assert "This log message won't be shown" in line
pytest.fail("A log message was shown and it shouldn't have been")
Expand Down

0 comments on commit 8d735f3

Please sign in to comment.