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