#8155: Preserve backward compatibility for test_support.check_warnings(). Add regression tests.
This commit is contained in:
parent
f3e9b2a996
commit
735885428d
|
@ -90,17 +90,17 @@ The goal for regression testing is to try to break code. This leads to a few
|
|||
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 @@ guidelines to be followed:
|
|||
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 @@ Running tests using :mod:`test.regrtest`
|
|||
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 @@ list of all resources and more command-line options, run :program:`python
|
|||
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 @@ This module defines the following exceptions:
|
|||
|
||||
.. 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 @@ The :mod:`test.test_support` module defines the following functions:
|
|||
.. 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 @@ The :mod:`test.test_support` module defines the following functions:
|
|||
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 @@ The :mod:`test.test_support` module defines the following functions:
|
|||
``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 @@ The :mod:`test.test_support` module defines the following functions:
|
|||
|
||||
.. 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 @@ The :mod:`test.test_support` module defines the following functions:
|
|||
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 @@ The :mod:`test.test_support` module defines the following classes:
|
|||
.. 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 @@ The :mod:`test.test_support` module defines the following classes:
|
|||
|
||||
.. 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 @@ The :mod:`test.test_support` module defines the following classes:
|
|||
:func:`check_warnings` above for more details.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
|
|
|
@ -577,14 +577,19 @@ def check_warnings(*filters, **kwargs):
|
|||
|
||||
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
|
||||
|
|
|
@ -633,19 +633,33 @@ class CatchWarningTests(BaseTest):
|
|||
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):
|
||||
|
|
Loading…
Reference in New Issue