#8155: Preserve backward compatibility for test_support.check_warnings(). Add regression tests.
diff --git a/Doc/library/test.rst b/Doc/library/test.rst
index 86f0af3..12ddb60 100644
--- a/Doc/library/test.rst
+++ b/Doc/library/test.rst
@@ -90,17 +90,17 @@
guidelines to be followed:
* The testing suite should exercise all classes, functions, and constants. This
- includes not just the external API that is to be presented to the outside world
- but also "private" code.
+ includes not just the external API that is to be presented to the outside
+ world but also "private" code.
* Whitebox testing (examining the code being tested when the tests are being
written) is preferred. Blackbox testing (testing only the published user
- interface) is not complete enough to make sure all boundary and edge cases are
- tested.
+ interface) is not complete enough to make sure all boundary and edge cases
+ are tested.
* Make sure all possible values are tested including invalid ones. This makes
- sure that not only all valid values are acceptable but also that improper values
- are handled correctly.
+ sure that not only all valid values are acceptable but also that improper
+ values are handled correctly.
* Exhaust as many code paths as possible. Test where branching occurs and thus
tailor input to make sure as many different paths through the code are taken.
@@ -120,8 +120,8 @@
behavior from side-effects of importing a module.
* Try to maximize code reuse. On occasion, tests will vary by something as small
- as what type of input is used. Minimize code duplication by subclassing a basic
- test class with a class that specifies the input::
+ as what type of input is used. Minimize code duplication by subclassing a
+ basic test class with a class that specifies the input::
class TestFuncAcceptsSequences(unittest.TestCase):
@@ -155,10 +155,10 @@
suite. Running the script by itself automatically starts running all regression
tests in the :mod:`test` package. It does this by finding all modules in the
package whose name starts with ``test_``, importing them, and executing the
-function :func:`test_main` if present. The names of tests to execute may also be
-passed to the script. Specifying a single regression test (:program:`python
-regrtest.py` :option:`test_spam.py`) will minimize output and only print whether
-the test passed or failed and thus minimize output.
+function :func:`test_main` if present. The names of tests to execute may also
+be passed to the script. Specifying a single regression test (:program:`python
+regrtest.py` :option:`test_spam.py`) will minimize output and only print
+whether the test passed or failed and thus minimize output.
Running :mod:`test.regrtest` directly allows what resources are available for
tests to use to be set. You do this by using the :option:`-u` command-line
@@ -173,10 +173,10 @@
regrtest.py` :option:`-h`.
Some other ways to execute the regression tests depend on what platform the
-tests are being executed on. On Unix, you can run :program:`make` :option:`test`
-at the top-level directory where Python was built. On Windows, executing
-:program:`rt.bat` from your :file:`PCBuild` directory will run all regression
-tests.
+tests are being executed on. On Unix, you can run :program:`make`
+:option:`test` at the top-level directory where Python was built. On Windows,
+executing :program:`rt.bat` from your :file:`PCBuild` directory will run all
+regression tests.
:mod:`test.test_support` --- Utility functions for tests
@@ -209,8 +209,9 @@
.. exception:: ResourceDenied
- Subclass of :exc:`unittest.SkipTest`. Raised when a resource (such as a network
- connection) is not available. Raised by the :func:`requires` function.
+ Subclass of :exc:`unittest.SkipTest`. Raised when a resource (such as a
+ network connection) is not available. Raised by the :func:`requires`
+ function.
The :mod:`test.test_support` module defines the following constants:
@@ -256,22 +257,23 @@
.. function:: requires(resource[, msg])
Raise :exc:`ResourceDenied` if *resource* is not available. *msg* is the
- argument to :exc:`ResourceDenied` if it is raised. Always returns True if called
- by a function whose ``__name__`` is ``'__main__'``. Used when tests are executed
- by :mod:`test.regrtest`.
+ argument to :exc:`ResourceDenied` if it is raised. Always returns
+ :const:`True` if called by a function whose ``__name__`` is ``'__main__'``.
+ Used when tests are executed by :mod:`test.regrtest`.
.. function:: findfile(filename)
- Return the path to the file named *filename*. If no match is found *filename* is
- returned. This does not equal a failure since it could be the path to the file.
+ Return the path to the file named *filename*. If no match is found
+ *filename* is returned. This does not equal a failure since it could be the
+ path to the file.
.. function:: run_unittest(*classes)
Execute :class:`unittest.TestCase` subclasses passed to the function. The
- function scans the classes for methods starting with the prefix ``test_`` and
- executes the tests individually.
+ function scans the classes for methods starting with the prefix ``test_``
+ and executes the tests individually.
It is also legal to pass strings as parameters; these should be keys in
``sys.modules``. Each associated module will be scanned by
@@ -284,7 +286,7 @@
This will run all tests defined in the named module.
-.. function:: check_warnings(*filters, quiet=False)
+.. function:: check_warnings(*filters, quiet=None)
A convenience wrapper for ``warnings.catch_warnings()`` that makes
it easier to test that a warning was correctly raised with a single
@@ -292,30 +294,31 @@
``warnings.catch_warnings(record=True)``.
It accepts 2-tuples ``("message regexp", WarningCategory)`` as positional
- arguments. When the optional keyword argument ``quiet`` is True, it does
- not fail if a filter catches nothing. Without argument, it defaults to::
+ arguments. If there's some ``*filters`` defined, or if the optional keyword
+ argument ``quiet`` is :const:`False`, it checks if the warnings are
+ effective. If some filter did not catch any warning, the test fails. If some
+ warnings are not caught, the test fails, too. To disable these checks, set
+ argument ``quiet`` to :const:`True`.
- check_warnings(("", Warning), quiet=False)
+ Without argument, it defaults to::
- The main difference is that it verifies the warnings raised. If some filter
- did not catch any warning, the test fails. If some warnings are not caught,
- the test fails, too. To disable these checks, use argument ``quiet=True``.
+ check_warnings(("", Warning), quiet=True)
- Another significant difference is that on entry to the context manager, a
- :class:`WarningRecorder` instance is returned instead of a simple list.
- The underlying warnings list is available via the recorder object's
- :attr:`warnings` attribute, while the attributes of the last raised
- warning are also accessible directly on the object. If no warning has
- been raised, then the latter attributes will all be :const:`None`.
+ Additionally, on entry to the context manager, a :class:`WarningRecorder`
+ instance is returned. The underlying warnings list is available via the
+ recorder object's :attr:`warnings` attribute, while the attributes of the
+ last raised warning are also accessible directly on the object. If no
+ warning has been raised, then the latter attributes will all be
+ :const:`None`.
A :meth:`reset` method is also provided on the recorder object. This
- method simply clears the warning list.
+ method simply clears the warnings list.
The context manager may be used like this::
import warnings
- with check_warnings():
+ with check_warnings(quiet=False):
exec('assert(False, "Hey!")')
warnings.warn(UserWarning("Hide me!"))
@@ -337,7 +340,6 @@
.. versionadded:: 2.6
.. versionchanged:: 2.7
- The test fails when the context manager do not catch any warning.
New optional attributes ``*filters`` and ``quiet``.
@@ -348,8 +350,9 @@
If ``sys.py3kwarning == 0``, it checks that no warning is raised.
It accepts 2-tuples ``("message regexp", WarningCategory)`` as positional
- arguments. When the optional keyword argument ``quiet`` is True, it does
- not fail if a filter catches nothing. Without argument, it defaults to::
+ arguments. When the optional keyword argument ``quiet`` is :const:`True`, it
+ does not fail if a filter catches nothing. Without argument, it defaults
+ to::
check_py3k_warnings(("", DeprecationWarning), quiet=False)
@@ -432,11 +435,11 @@
.. versionadded:: 2.6
.. class:: EnvironmentVarGuard()
- Class used to temporarily set or unset environment variables. Instances can be
- used as a context manager and have a complete dictionary interface for
- querying/modifying the underlying ``os.environ``. After exit from the context
- manager all changes to environment variables done through this instance will
- be rolled back.
+ Class used to temporarily set or unset environment variables. Instances can
+ be used as a context manager and have a complete dictionary interface for
+ querying/modifying the underlying ``os.environ``. After exit from the
+ context manager all changes to environment variables done through this
+ instance will be rolled back.
.. versionadded:: 2.6
.. versionchanged:: 2.7
@@ -445,7 +448,8 @@
.. method:: EnvironmentVarGuard.set(envvar, value)
- Temporarily set the environment variable ``envvar`` to the value of ``value``.
+ Temporarily set the environment variable ``envvar`` to the value of
+ ``value``.
.. method:: EnvironmentVarGuard.unset(envvar)
@@ -459,4 +463,3 @@
:func:`check_warnings` above for more details.
.. versionadded:: 2.6
-
diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
index 9bb4329..75daacb 100644
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -577,14 +577,19 @@
Optional argument:
- if 'quiet' is True, it does not fail if a filter catches nothing
- (default False)
+ (default True without argument,
+ default False if some filters are defined)
Without argument, it defaults to:
- check_warnings(("", Warning), quiet=False)
+ check_warnings(("", Warning), quiet=True)
"""
+ quiet = kwargs.get('quiet')
if not filters:
filters = (("", Warning),)
- return _filterwarnings(filters, kwargs.get('quiet'))
+ # Preserve backward compatibility
+ if quiet is None:
+ quiet = True
+ return _filterwarnings(filters, quiet)
@contextlib.contextmanager
diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py
index e008984..79922b2 100644
--- a/Lib/test/test_warnings.py
+++ b/Lib/test/test_warnings.py
@@ -633,19 +633,33 @@
def test_check_warnings(self):
# Explicit tests for the test_support convenience wrapper
wmod = self.module
- if wmod is sys.modules['warnings']:
- with test_support.check_warnings() as w:
- self.assertEqual(w.warnings, [])
- wmod.simplefilter("always")
- wmod.warn("foo")
- self.assertEqual(str(w.message), "foo")
- wmod.warn("bar")
- self.assertEqual(str(w.message), "bar")
- self.assertEqual(str(w.warnings[0].message), "foo")
- self.assertEqual(str(w.warnings[1].message), "bar")
- w.reset()
- self.assertEqual(w.warnings, [])
+ if wmod is not sys.modules['warnings']:
+ return
+ with test_support.check_warnings(quiet=False) as w:
+ self.assertEqual(w.warnings, [])
+ wmod.simplefilter("always")
+ wmod.warn("foo")
+ self.assertEqual(str(w.message), "foo")
+ wmod.warn("bar")
+ self.assertEqual(str(w.message), "bar")
+ self.assertEqual(str(w.warnings[0].message), "foo")
+ self.assertEqual(str(w.warnings[1].message), "bar")
+ w.reset()
+ self.assertEqual(w.warnings, [])
+ with test_support.check_warnings():
+ # defaults to quiet=True without argument
+ pass
+ with test_support.check_warnings(('foo', UserWarning)):
+ wmod.warn("foo")
+
+ with self.assertRaises(AssertionError):
+ with test_support.check_warnings(('', RuntimeWarning)):
+ # defaults to quiet=False with argument
+ pass
+ with self.assertRaises(AssertionError):
+ with test_support.check_warnings(('foo', RuntimeWarning)):
+ wmod.warn("foo")
class CCatchWarningTests(CatchWarningTests):