Display node ids and the warnings generated by it
The rationale of using node ids is that users can copy/paste it to run a chosen test
This commit is contained in:
parent
bddb922f7b
commit
272afa9422
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
This is a good source for looking at the various reporting hooks.
|
This is a good source for looking at the various reporting hooks.
|
||||||
"""
|
"""
|
||||||
|
import operator
|
||||||
|
import itertools
|
||||||
|
|
||||||
from _pytest.main import EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, \
|
from _pytest.main import EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, \
|
||||||
EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED
|
EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED
|
||||||
import pytest
|
import pytest
|
||||||
|
@ -28,7 +31,7 @@ def pytest_addoption(parser):
|
||||||
"--disable-warnings is set")
|
"--disable-warnings is set")
|
||||||
group._addoption('--disable-warnings', '--disable-pytest-warnings', default=False,
|
group._addoption('--disable-warnings', '--disable-pytest-warnings', default=False,
|
||||||
dest='disable_warnings', action='store_true',
|
dest='disable_warnings', action='store_true',
|
||||||
help='disable warnings summary, overrides -r w flag')
|
help='disable warnings summary')
|
||||||
group._addoption('-l', '--showlocals',
|
group._addoption('-l', '--showlocals',
|
||||||
action="store_true", dest="showlocals", default=False,
|
action="store_true", dest="showlocals", default=False,
|
||||||
help="show locals in tracebacks (disabled by default).")
|
help="show locals in tracebacks (disabled by default).")
|
||||||
|
@ -438,16 +441,15 @@ class TerminalReporter(object):
|
||||||
|
|
||||||
def summary_warnings(self):
|
def summary_warnings(self):
|
||||||
if self.hasopt("w"):
|
if self.hasopt("w"):
|
||||||
warnings = self.stats.get("warnings")
|
all_warnings = self.stats.get("warnings")
|
||||||
if not warnings:
|
if not all_warnings:
|
||||||
return
|
return
|
||||||
self.write_sep("=", "warnings summary")
|
self.write_sep("=", "warnings summary", yellow=True, bold=False)
|
||||||
for w in warnings:
|
grouped = itertools.groupby(all_warnings, key=operator.attrgetter('nodeid'))
|
||||||
msg = ''
|
for nodeid, warnings in grouped:
|
||||||
if w.fslocation:
|
self._tw.line(str(nodeid))
|
||||||
msg += str(w.fslocation) + ' '
|
for w in warnings:
|
||||||
msg += w.message
|
self._tw.line(w.message)
|
||||||
self._tw.line(msg)
|
|
||||||
self._tw.line('-- Docs: http://doc.pytest.org/en/latest/warnings.html')
|
self._tw.line('-- Docs: http://doc.pytest.org/en/latest/warnings.html')
|
||||||
|
|
||||||
def summary_passes(self):
|
def summary_passes(self):
|
||||||
|
|
|
@ -63,7 +63,7 @@ def catch_warnings_for_item(item):
|
||||||
msg = warnings.formatwarning(
|
msg = warnings.formatwarning(
|
||||||
warning.message, warning.category,
|
warning.message, warning.category,
|
||||||
warning.filename, warning.lineno, warning.line)
|
warning.filename, warning.lineno, warning.line)
|
||||||
item.config.warn("unused", msg, fslocation=None)
|
item.warn("unused", msg)
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl(hookwrapper=True)
|
@pytest.hookimpl(hookwrapper=True)
|
||||||
|
|
|
@ -4,27 +4,48 @@ import pytest
|
||||||
WARNINGS_SUMMARY_HEADER = 'warnings summary'
|
WARNINGS_SUMMARY_HEADER = 'warnings summary'
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def pyfile_with_warnings(testdir):
|
def pyfile_with_warnings(testdir, request):
|
||||||
testdir.makepyfile('''
|
"""
|
||||||
import warnings
|
Create a test file which calls a function in a module which generates warnings.
|
||||||
def test_func():
|
"""
|
||||||
warnings.warn(PendingDeprecationWarning("functionality is pending deprecation"))
|
testdir.syspathinsert()
|
||||||
warnings.warn(DeprecationWarning("functionality is deprecated"))
|
test_name = request.function.__name__
|
||||||
''')
|
module_name = test_name.lstrip('test_') + '_module'
|
||||||
|
testdir.makepyfile(**{
|
||||||
|
module_name: '''
|
||||||
|
import warnings
|
||||||
|
def foo():
|
||||||
|
warnings.warn(PendingDeprecationWarning("functionality is pending deprecation"))
|
||||||
|
warnings.warn(DeprecationWarning("functionality is deprecated"))
|
||||||
|
return 1
|
||||||
|
''',
|
||||||
|
test_name: '''
|
||||||
|
import {module_name}
|
||||||
|
def test_func():
|
||||||
|
assert {module_name}.foo() == 1
|
||||||
|
'''.format(module_name=module_name)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def test_normal_flow(testdir, pyfile_with_warnings):
|
def test_normal_flow(testdir, pyfile_with_warnings):
|
||||||
|
"""
|
||||||
|
Check that the warnings section is displayed, containing test node ids followed by
|
||||||
|
all warnings generated by that test node.
|
||||||
|
"""
|
||||||
result = testdir.runpytest()
|
result = testdir.runpytest()
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,
|
'*== %s ==*' % WARNINGS_SUMMARY_HEADER,
|
||||||
|
|
||||||
'*test_normal_flow.py:3: PendingDeprecationWarning: functionality is pending deprecation',
|
'*test_normal_flow.py::test_func',
|
||||||
|
|
||||||
|
'*normal_flow_module.py:3: PendingDeprecationWarning: functionality is pending deprecation',
|
||||||
' warnings.warn(PendingDeprecationWarning("functionality is pending deprecation"))',
|
' warnings.warn(PendingDeprecationWarning("functionality is pending deprecation"))',
|
||||||
|
|
||||||
'*test_normal_flow.py:4: DeprecationWarning: functionality is deprecated',
|
'*normal_flow_module.py:4: DeprecationWarning: functionality is deprecated',
|
||||||
' warnings.warn(DeprecationWarning("functionality is deprecated"))',
|
' warnings.warn(DeprecationWarning("functionality is deprecated"))',
|
||||||
'* 1 passed, 2 warnings*',
|
'* 1 passed, 2 warnings*',
|
||||||
])
|
])
|
||||||
|
assert result.stdout.str().count('test_normal_flow.py::test_func') == 1
|
||||||
|
|
||||||
|
|
||||||
def test_setup_teardown_warnings(testdir, pyfile_with_warnings):
|
def test_setup_teardown_warnings(testdir, pyfile_with_warnings):
|
||||||
|
@ -66,7 +87,7 @@ def test_as_errors(testdir, pyfile_with_warnings, method):
|
||||||
result = testdir.runpytest(*args)
|
result = testdir.runpytest(*args)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
'E PendingDeprecationWarning: functionality is pending deprecation',
|
'E PendingDeprecationWarning: functionality is pending deprecation',
|
||||||
'test_as_errors.py:3: PendingDeprecationWarning',
|
'as_errors_module.py:3: PendingDeprecationWarning',
|
||||||
'* 1 failed in *',
|
'* 1 failed in *',
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue