Merge pull request #4665 from nicoddemus/group-warnings-by-message

Group warnings by message instead of by test id
This commit is contained in:
Bruno Oliveira 2019-01-24 20:00:27 -02:00 committed by GitHub
commit 7ddfc04793
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 60 additions and 21 deletions

View File

@ -0,0 +1,4 @@
Warning summary now groups warnings by message instead of by test id.
This makes the output more compact and better conveys the general idea of how much code is
actually generating warnings, instead of how many tests call that code.

View File

@ -7,7 +7,7 @@ from __future__ import division
from __future__ import print_function from __future__ import print_function
import argparse import argparse
import itertools import collections
import platform import platform
import sys import sys
import time import time
@ -727,33 +727,33 @@ class TerminalReporter(object):
final = hasattr(self, "_already_displayed_warnings") final = hasattr(self, "_already_displayed_warnings")
if final: if final:
warnings = all_warnings[self._already_displayed_warnings :] warning_reports = all_warnings[self._already_displayed_warnings :]
else: else:
warnings = all_warnings warning_reports = all_warnings
self._already_displayed_warnings = len(warnings) self._already_displayed_warnings = len(warning_reports)
if not warnings: if not warning_reports:
return return
grouped = itertools.groupby( reports_grouped_by_message = collections.OrderedDict()
warnings, key=lambda wr: wr.get_location(self.config) for wr in warning_reports:
) reports_grouped_by_message.setdefault(wr.message, []).append(wr)
title = "warnings summary (final)" if final else "warnings summary" title = "warnings summary (final)" if final else "warnings summary"
self.write_sep("=", title, yellow=True, bold=False) self.write_sep("=", title, yellow=True, bold=False)
for location, warning_records in grouped: for message, warning_reports in reports_grouped_by_message.items():
# legacy warnings show their location explicitly, while standard warnings look better without has_any_location = False
# it because the location is already formatted into the message for w in warning_reports:
warning_records = list(warning_records) location = w.get_location(self.config)
if location:
self._tw.line(str(location))
for w in warning_records:
if location: if location:
lines = w.message.splitlines() self._tw.line(str(location))
indented = "\n".join(" " + x for x in lines) has_any_location = True
message = indented.rstrip() if has_any_location:
else: lines = message.splitlines()
message = w.message.rstrip() indented = "\n".join(" " + x for x in lines)
self._tw.line(message) message = indented.rstrip()
else:
message = message.rstrip()
self._tw.line(message)
self._tw.line() self._tw.line()
self._tw.line("-- Docs: https://docs.pytest.org/en/latest/warnings.html") self._tw.line("-- Docs: https://docs.pytest.org/en/latest/warnings.html")

View File

@ -0,0 +1,16 @@
import warnings
import pytest
def func():
warnings.warn(UserWarning("foo"))
@pytest.mark.parametrize("i", range(5))
def test_foo(i):
func()
def test_bar():
func()

View File

@ -693,3 +693,22 @@ def test_warnings_checker_twice():
warnings.warn("Message A", UserWarning) warnings.warn("Message A", UserWarning)
with expectation: with expectation:
warnings.warn("Message B", UserWarning) warnings.warn("Message B", UserWarning)
@pytest.mark.filterwarnings("always")
def test_group_warnings_by_message(testdir):
testdir.copy_example("warnings/test_group_warnings_by_message.py")
result = testdir.runpytest()
result.stdout.fnmatch_lines(
[
"test_group_warnings_by_message.py::test_foo[0]",
"test_group_warnings_by_message.py::test_foo[1]",
"test_group_warnings_by_message.py::test_foo[2]",
"test_group_warnings_by_message.py::test_foo[3]",
"test_group_warnings_by_message.py::test_foo[4]",
"test_group_warnings_by_message.py::test_bar",
]
)
warning_code = 'warnings.warn(UserWarning("foo"))'
assert warning_code in result.stdout.str()
assert result.stdout.str().count(warning_code) == 1