Skip to content

Commit bef5b2e

Browse files
committed
Improve PipTestEnvironment to check for logging errors.
1 parent dc12177 commit bef5b2e

File tree

2 files changed

+57
-7
lines changed

2 files changed

+57
-7
lines changed

tests/lib/__init__.py

+30-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import absolute_import
22

33
from contextlib import contextmanager
4+
from textwrap import dedent
45
import os
56
import sys
67
import re
@@ -263,6 +264,17 @@ def assert_installed(self, pkg_name, editable=True, with_files=[],
263264
)
264265

265266

267+
def make_check_stderr_message(stderr, line, reason):
268+
"""
269+
Create an exception message to use inside check_stderr().
270+
"""
271+
return dedent("""\
272+
{reason}:
273+
Caused by line: {line!r}
274+
Complete stderr: {stderr}
275+
""").format(stderr=stderr, line=line, reason=reason)
276+
277+
266278
def check_stderr(
267279
stderr, allow_stderr_warning=None, allow_stderr_error=None,
268280
):
@@ -293,22 +305,34 @@ def check_stderr(
293305

294306
lines = stderr.splitlines()
295307
for line in lines:
308+
# First check for logging errors which are sent directly to stderr
309+
# and so bypass any configured log formatter. The
310+
# "--- Logging error ---" string is used in Python 3.4+, and
311+
# "Logged from file " is used in Python 2.
312+
if (line.startswith('--- Logging error ---') or
313+
line.startswith('Logged from file ')):
314+
reason = 'stderr has a logging error, which is never allowed'
315+
msg = make_check_stderr_message(stderr, line=line, reason=reason)
316+
raise RuntimeError(msg)
317+
296318
if line.startswith('ERROR: '):
297-
raise RuntimeError(
319+
reason = (
298320
'stderr has an unexpected error '
299-
'(pass allow_stderr_error=True to permit this): {}'
300-
.format(line)
321+
'(pass allow_stderr_error=True to permit this)'
301322
)
323+
msg = make_check_stderr_message(stderr, line=line, reason=reason)
324+
raise RuntimeError(msg)
302325
if allow_stderr_warning:
303326
continue
304327

305328
if (line.startswith('WARNING: ') or
306329
line.startswith(DEPRECATION_MSG_PREFIX)):
307-
raise RuntimeError(
330+
reason = (
308331
'stderr has an unexpected warning '
309-
'(pass allow_stderr_warning=True to permit this): {}'
310-
.format(line)
332+
'(pass allow_stderr_warning=True to permit this)'
311333
)
334+
msg = make_check_stderr_message(stderr, line=line, reason=reason)
335+
raise RuntimeError(msg)
312336

313337

314338
class PipTestEnvironment(TestFileEnvironment):

tests/lib/test_lib.py

+27-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ def assert_error_startswith(exc_type, expected_start):
2020
with pytest.raises(exc_type) as err:
2121
yield
2222

23-
assert str(err.value).startswith(expected_start)
23+
assert str(err.value).startswith(expected_start), (
24+
'full message: {}'.format(err.value)
25+
)
2426

2527

2628
def test_tmp_dir_exists_in_env(script):
@@ -78,6 +80,18 @@ def test_as_import(script):
7880

7981
class TestPipTestEnvironment:
8082

83+
def run_with_log_command(self, script, sub_string):
84+
"""
85+
Call run() on a command that logs a "%"-style format string using
86+
the given substring as the string's replacement field.
87+
"""
88+
command = (
89+
"import logging; logging.basicConfig(level='INFO'); "
90+
"logging.getLogger().info('sub: {}', 'foo')"
91+
).format(sub_string)
92+
args = [sys.executable, '-c', command]
93+
script.run(*args)
94+
8195
def run_stderr_with_prefix(self, script, prefix, **kwargs):
8296
"""
8397
Call run() that prints stderr with the given prefix.
@@ -139,6 +153,18 @@ def test_run__unexpected_stderr(self, script, prefix, expected_start):
139153
with assert_error_startswith(RuntimeError, expected_start):
140154
self.run_stderr_with_prefix(script, prefix)
141155

156+
def test_run__logging_error(self, script):
157+
"""
158+
Test calling run() with an unexpected logging error.
159+
"""
160+
# Pass a good substitution string.
161+
self.run_with_log_command(script, sub_string='%r')
162+
163+
expected_start = 'stderr has a logging error, which is never allowed'
164+
with assert_error_startswith(RuntimeError, expected_start):
165+
# Pass a bad substitution string.
166+
self.run_with_log_command(script, sub_string='{!r}')
167+
142168
def test_run__allow_stderr_error_false_error_with_expect_error(
143169
self, script,
144170
):

0 commit comments

Comments
 (0)