Skip to content

Commit 2e98d39

Browse files
committed
Allow finer-grained testing of subprocess stderr.
1 parent 8ef3283 commit 2e98d39

File tree

1 file changed

+72
-3
lines changed

1 file changed

+72
-3
lines changed

tests/lib/__init__.py

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import pytest
1313
from scripttest import FoundDir, TestFileEnvironment
1414

15+
from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX
1516
from tests.lib.path import Path, curdir
1617

1718
DATA_DIR = Path(__file__).folder.folder.join("data").abspath
@@ -262,6 +263,46 @@ def assert_installed(self, pkg_name, editable=True, with_files=[],
262263
)
263264

264265

266+
def check_stderr(
267+
stderr, expect_stderr_warning=False, expect_stderr_error=False,
268+
):
269+
"""
270+
Check the given stderr for logged warnings and errors.
271+
272+
:param stderr: stderr output as a string.
273+
:param expect_stderr_warning: whether a logged warning (or deprecation
274+
message) is allowed.
275+
:param expect_stderr_error: whether a logged error is allowed. Passing
276+
True for this argument implies `expect_stderr_warning` since warnings
277+
are weaker than errors.
278+
"""
279+
if expect_stderr_error:
280+
expect_stderr_warning = True
281+
282+
if expect_stderr_error:
283+
# Then any stderr is acceptable.
284+
return
285+
286+
lines = stderr.splitlines()
287+
for line in lines:
288+
if line.startswith('ERROR: '):
289+
raise RuntimeError(
290+
'stderr has an unexpected error '
291+
'(pass expect_stderr_error=True to permit this): {}'
292+
.format(line)
293+
)
294+
if expect_stderr_warning:
295+
continue
296+
297+
if (line.startswith('WARNING: ') or
298+
line.startswith(DEPRECATION_MSG_PREFIX)):
299+
raise RuntimeError(
300+
'stderr has an unexpected warning '
301+
'(pass expect_stderr_warning=True to permit this): {}'
302+
.format(line)
303+
)
304+
305+
265306
class PipTestEnvironment(TestFileEnvironment):
266307
"""
267308
A specialized TestFileEnvironment for testing pip
@@ -368,6 +409,17 @@ def _find_traverse(self, path, result):
368409
super(PipTestEnvironment, self)._find_traverse(path, result)
369410

370411
def run(self, *args, **kw):
412+
"""
413+
:param expect_stderr_warning: whether a logged warning (or
414+
deprecation message) is allowed in stderr.
415+
:param expect_stderr_error: whether a logged error is allowed in
416+
stderr. Passing True for this argument implies
417+
`expect_stderr_warning` since warnings are weaker than errors.
418+
:param expect_stderr: allow any stderr (equivalent to passing
419+
`expect_stderr_error`). This argument is an abbreviated version
420+
of `expect_stderr_error` and is also kept for backwards
421+
compatibility.
422+
"""
371423
if self.verbose:
372424
print('>> running %s %s' % (args, kw))
373425
cwd = kw.pop('cwd', None)
@@ -377,11 +429,28 @@ def run(self, *args, **kw):
377429
if sys.platform == 'win32':
378430
# Partial fix for ScriptTest.run using `shell=True` on Windows.
379431
args = [str(a).replace('^', '^^').replace('&', '^&') for a in args]
380-
return TestPipResult(
381-
super(PipTestEnvironment, self).run(cwd=cwd, *args, **kw),
382-
verbose=self.verbose,
432+
433+
# Remove `expect_stderr_error` and `expect_stderr_warning` because
434+
# those arguments are not supported by PipTestEnvironment.
435+
expect_stderr_error = kw.pop('expect_stderr_error', False)
436+
expect_stderr_warning = kw.pop('expect_stderr_warning', False)
437+
438+
if kw.get('expect_error') or kw.get('expect_stderr'):
439+
# Then default to allowing logged errors.
440+
expect_stderr_error = True
441+
442+
# Pass expect_stderr=True to allow any stderr. We do this because
443+
# we do our checking of stderr further on in check_stderr().
444+
kw['expect_stderr'] = True
445+
result = super(PipTestEnvironment, self).run(cwd=cwd, *args, **kw)
446+
447+
check_stderr(
448+
result.stderr, expect_stderr_error=expect_stderr_error,
449+
expect_stderr_warning=expect_stderr_warning,
383450
)
384451

452+
return TestPipResult(result, verbose=self.verbose)
453+
385454
def pip(self, *args, **kwargs):
386455
if self.pip_expect_stderr:
387456
kwargs['expect_stderr'] = True

0 commit comments

Comments
 (0)