From 0cf45ee18a48061163cfd82c1edf1d6292d2a2a4 Mon Sep 17 00:00:00 2001
From: Daniel Hahler <git@thequod.de>
Date: Thu, 15 Nov 2018 17:05:56 +0100
Subject: [PATCH] Display "short test summary info" after (main) warnings again

Fixes https://github.com/pytest-dev/pytest/issues/3952.
---
 changelog/3952.bugfix.rst |  1 +
 src/_pytest/terminal.py   | 16 +++++++++++++---
 testing/test_terminal.py  | 20 ++++++++++++++++++--
 3 files changed, 32 insertions(+), 5 deletions(-)
 create mode 100644 changelog/3952.bugfix.rst

diff --git a/changelog/3952.bugfix.rst b/changelog/3952.bugfix.rst
new file mode 100644
index 000000000..e999cdded
--- /dev/null
+++ b/changelog/3952.bugfix.rst
@@ -0,0 +1 @@
+Display warnings before "short test summary info" again, but still later warnings in the end.
diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py
index 94ad32e0f..3c9abac8a 100644
--- a/src/_pytest/terminal.py
+++ b/src/_pytest/terminal.py
@@ -647,9 +647,11 @@ class TerminalReporter(object):
     def pytest_terminal_summary(self):
         self.summary_errors()
         self.summary_failures()
-        yield
         self.summary_warnings()
+        yield
         self.summary_passes()
+        # Display any extra warnings from teardown here (if any).
+        self.summary_warnings()
 
     def pytest_keyboard_interrupt(self, excinfo):
         self._keyboardinterrupt_memo = excinfo.getrepr(funcargs=True)
@@ -726,11 +728,19 @@ class TerminalReporter(object):
             if not all_warnings:
                 return
 
+            final = hasattr(self, "_already_displayed_warnings")
+            if final:
+                warnings = all_warnings[self._already_displayed_warnings :]
+            else:
+                warnings = all_warnings
+            self._already_displayed_warnings = len(warnings)
+
             grouped = itertools.groupby(
-                all_warnings, key=lambda wr: wr.get_location(self.config)
+                warnings, key=lambda wr: wr.get_location(self.config)
             )
 
-            self.write_sep("=", "warnings summary", yellow=True, bold=False)
+            title = "warnings summary (final)" if final else "warnings summary"
+            self.write_sep("=", title, yellow=True, bold=False)
             for location, warning_records in grouped:
                 # legacy warnings show their location explicitly, while standard warnings look better without
                 # it because the location is already formatted into the message
diff --git a/testing/test_terminal.py b/testing/test_terminal.py
index a028f9c22..f1bfa81f2 100644
--- a/testing/test_terminal.py
+++ b/testing/test_terminal.py
@@ -1074,11 +1074,27 @@ def test_terminal_summary_warnings_are_displayed(testdir):
             warnings.warn(UserWarning('internal warning'))
     """
     )
-    result = testdir.runpytest()
+    testdir.makepyfile(
+        """
+        def test_failure():
+            import warnings
+            warnings.warn("warning_from_" + "test")
+            assert 0
+    """
+    )
+    result = testdir.runpytest("-ra")
     result.stdout.fnmatch_lines(
-        ["*conftest.py:3:*internal warning", "*== 1 warnings in *"]
+        [
+            "*= warnings summary =*",
+            "*warning_from_test*",
+            "*= short test summary info =*",
+            "*= warnings summary (final) =*",
+            "*conftest.py:3:*internal warning",
+            "*== 1 failed, 2 warnings in *",
+        ]
     )
     assert "None" not in result.stdout.str()
+    assert result.stdout.str().count("warning_from_test") == 1
 
 
 @pytest.mark.parametrize(