From 53b506beda2e959928661f960d6b7bff5e300adb Mon Sep 17 00:00:00 2001 From: Florent Xicluna Date: Thu, 18 Mar 2010 20:00:57 +0000 Subject: [PATCH] Merged revisions 79049 via svnmerge from svn+ssh://pythondev@svn.python.org/python/trunk ........ r79049 | florent.xicluna | 2010-03-18 20:51:47 +0100 (jeu, 18 mar 2010) | 2 lines #8155: Preserve backward compatibility for test_support.check_warnings(). Add regression tests. ........ --- Doc/library/test.rst | 98 ++++++++++++++++++++------------------- Lib/test/support.py | 11 +++-- Lib/test/test_warnings.py | 37 ++++++++++----- 3 files changed, 84 insertions(+), 62 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst index d8dd46c26e..351c032452 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -89,17 +89,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. @@ -119,8 +119,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): @@ -154,10 +154,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 @@ -172,10 +172,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.support` --- Utility functions for tests @@ -200,8 +200,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.support` module defines the following constants: @@ -242,22 +243,23 @@ The :mod:`test.support` module defines the following functions: .. function:: requires(resource, msg=None) 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 @@ -270,7 +272,7 @@ The :mod:`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 @@ -278,30 +280,31 @@ The :mod:`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!")) @@ -322,7 +325,6 @@ The :mod:`test.support` module defines the following functions: assert len(w.warnings) == 0 .. versionchanged:: 2.7 - The test fails when the context manager do not catch any warning. New optional attributes ``*filters`` and ``quiet``. @@ -400,18 +402,19 @@ The :mod:`test.support` module defines the following classes: .. 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. .. versionchanged:: 3.1 Added dictionary interface. .. 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) @@ -423,4 +426,3 @@ The :mod:`test.support` module defines the following classes: Class used to record warnings for unit tests. See documentation of :func:`check_warnings` above for more details. - diff --git a/Lib/test/support.py b/Lib/test/support.py index 28f7e2766d..73c4228804 100644 --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -534,14 +534,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) class CleanImport(object): diff --git a/Lib/test/test_warnings.py b/Lib/test/test_warnings.py index d5876a7e66..dda704e22f 100644 --- a/Lib/test/test_warnings.py +++ b/Lib/test/test_warnings.py @@ -644,18 +644,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 support.check_warnings() as w: - self.assertEqual(w.warnings, []) - wmod.simplefilter("always") + if wmod is not sys.modules['warnings']: + return + with 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 support.check_warnings(): + # defaults to quiet=True without argument + pass + with support.check_warnings(('foo', UserWarning)): + wmod.warn("foo") + + with self.assertRaises(AssertionError): + with support.check_warnings(('', RuntimeWarning)): + # defaults to quiet=False with argument + pass + with self.assertRaises(AssertionError): + with support.check_warnings(('foo', RuntimeWarning)): 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, []) class CCatchWarningTests(CatchWarningTests): module = c_warnings -- 2.40.0