Implement a contextmanager test.test_support.catch_warning that can

be used to catch the last warning issued by the warning framework.

Change test_warnings.py and test_structmembers.py to use this
new contextmanager.
This commit is contained in:
Walter Dörwald 2007-04-03 18:33:29 +00:00
parent c4a106733c
commit e6dae6c655
4 changed files with 127 additions and 109 deletions

View File

@ -4,7 +4,7 @@ from _testcapi import test_structmembersType, \
INT_MAX, INT_MIN, UINT_MAX, \
LONG_MAX, LONG_MIN, ULONG_MAX
import warnings, exceptions, unittest, test.test_warnings
import warnings, exceptions, unittest
from test import test_support
ts=test_structmembersType(1,2,3,4,5,6,7,8,9.99999,10.1010101010)
@ -39,34 +39,39 @@ class ReadWriteTests(unittest.TestCase):
ts.T_ULONG=ULONG_MAX
self.assertEquals(ts.T_ULONG, ULONG_MAX)
class TestWarnings(test.test_warnings.CatchWarningTest):
def has_warned(self):
self.assertEqual(test.test_warnings.msg.category,
exceptions.RuntimeWarning.__name__)
class TestWarnings(unittest.TestCase):
def has_warned(self, w):
self.assert_(w.category is RuntimeWarning)
def test_byte_max(self):
ts.T_BYTE=CHAR_MAX+1
self.has_warned()
with test_support.catch_warning() as w:
ts.T_BYTE=CHAR_MAX+1
self.has_warned(w)
def test_byte_min(self):
ts.T_BYTE=CHAR_MIN-1
self.has_warned()
with test_support.catch_warning() as w:
ts.T_BYTE=CHAR_MIN-1
self.has_warned(w)
def test_ubyte_max(self):
ts.T_UBYTE=UCHAR_MAX+1
self.has_warned()
with test_support.catch_warning() as w:
ts.T_UBYTE=UCHAR_MAX+1
self.has_warned(w)
def test_short_max(self):
ts.T_SHORT=SHRT_MAX+1
self.has_warned()
with test_support.catch_warning() as w:
ts.T_SHORT=SHRT_MAX+1
self.has_warned(w)
def test_short_min(self):
ts.T_SHORT=SHRT_MIN-1
self.has_warned()
with test_support.catch_warning() as w:
ts.T_SHORT=SHRT_MIN-1
self.has_warned(w)
def test_ushort_max(self):
ts.T_USHORT=USHRT_MAX+1
self.has_warned()
with test_support.catch_warning() as w:
ts.T_USHORT=USHRT_MAX+1
self.has_warned(w)

View File

@ -282,6 +282,42 @@ def guard_warnings_filter():
finally:
warnings.filters = original_filters
class WarningMessage(object):
"Holds the result of the latest showwarning() call"
def __init__(self):
self.message = None
self.category = None
self.filename = None
self.lineno = None
def _showwarning(self, message, category, filename, lineno, file=None):
self.message = message
self.category = category
self.filename = filename
self.lineno = lineno
@contextlib.contextmanager
def catch_warning():
"""
Guard the warnings filter from being permanently changed and record the
data of the last warning that has been issued.
Use like this:
with catch_warning as w:
warnings.warn("foo")
assert str(w.message) == "foo"
"""
warning = WarningMessage()
original_filters = warnings.filters[:]
original_showwarning = warnings.showwarning
warnings.showwarning = warning._showwarning
try:
yield warning
finally:
warnings.showwarning = original_showwarning
warnings.filters = original_filters
class EnvironmentVarGuard(object):
"""Class to help protect the environment variable properly. Can be used as

View File

@ -5,121 +5,95 @@ from test import test_support
import warning_tests
# The warnings module isn't easily tested, because it relies on module
# globals to store configuration information. setUp() and tearDown()
# preserve the current settings to avoid bashing them while running tests.
# To capture the warning messages, a replacement for showwarning() is
# used to save warning information in a global variable.
class WarningMessage:
"Holds results of latest showwarning() call"
pass
def showwarning(message, category, filename, lineno, file=None):
msg.message = str(message)
msg.category = category.__name__
msg.filename = os.path.basename(filename)
msg.lineno = lineno
class CatchWarningTest(unittest.TestCase):
# base class used for catching warnings issued by the
# warning framework (this is reused by test_structmembers.py)
class TestModule(unittest.TestCase):
def setUp(self):
global msg
msg = WarningMessage()
self._filters = warnings.filters[:]
self._showwarning = warnings.showwarning
warnings.showwarning = showwarning
self.ignored = [w[2].__name__ for w in self._filters
self.ignored = [w[2].__name__ for w in warnings.filters
if w[0]=='ignore' and w[1] is None and w[3] is None]
def tearDown(self):
warnings.filters = self._filters[:]
warnings.showwarning = self._showwarning
class TestModule(CatchWarningTest):
def test_warn_default_category(self):
for i in range(4):
text = 'multi %d' %i # Different text on each call
warnings.warn(text)
self.assertEqual(msg.message, text)
self.assertEqual(msg.category, 'UserWarning')
with test_support.catch_warning() as w:
for i in range(4):
text = 'multi %d' %i # Different text on each call
warnings.warn(text)
self.assertEqual(str(w.message), text)
self.assert_(w.category is UserWarning)
def test_warn_specific_category(self):
text = 'None'
for category in [DeprecationWarning, FutureWarning,
PendingDeprecationWarning, RuntimeWarning,
SyntaxWarning, UserWarning, Warning]:
if category.__name__ in self.ignored:
text = 'filtered out' + category.__name__
warnings.warn(text, category)
self.assertNotEqual(msg.message, text)
else:
text = 'unfiltered %s' % category.__name__
warnings.warn(text, category)
self.assertEqual(msg.message, text)
self.assertEqual(msg.category, category.__name__)
with test_support.catch_warning() as w:
text = 'None'
for category in [DeprecationWarning, FutureWarning,
PendingDeprecationWarning, RuntimeWarning,
SyntaxWarning, UserWarning, Warning]:
if category.__name__ in self.ignored:
text = 'filtered out' + category.__name__
warnings.warn(text, category)
self.assertNotEqual(w.message, text)
else:
text = 'unfiltered %s' % category.__name__
warnings.warn(text, category)
self.assertEqual(str(w.message), text)
self.assert_(w.category is category)
def test_filtering(self):
with test_support.catch_warning() as w:
warnings.filterwarnings("error", "", Warning, "", 0)
self.assertRaises(UserWarning, warnings.warn, 'convert to error')
warnings.filterwarnings("error", "", Warning, "", 0)
self.assertRaises(UserWarning, warnings.warn, 'convert to error')
warnings.resetwarnings()
text = 'handle normally'
warnings.warn(text)
self.assertEqual(str(w.message), text)
self.assert_(w.category is UserWarning)
warnings.resetwarnings()
text = 'handle normally'
warnings.warn(text)
self.assertEqual(msg.message, text)
self.assertEqual(msg.category, 'UserWarning')
warnings.filterwarnings("ignore", "", Warning, "", 0)
text = 'filtered out'
warnings.warn(text)
self.assertNotEqual(str(w.message), text)
warnings.filterwarnings("ignore", "", Warning, "", 0)
text = 'filtered out'
warnings.warn(text)
self.assertNotEqual(msg.message, text)
warnings.resetwarnings()
warnings.filterwarnings("error", "hex*", Warning, "", 0)
self.assertRaises(UserWarning, warnings.warn, 'hex/oct')
text = 'nonmatching text'
warnings.warn(text)
self.assertEqual(msg.message, text)
self.assertEqual(msg.category, 'UserWarning')
warnings.resetwarnings()
warnings.filterwarnings("error", "hex*", Warning, "", 0)
self.assertRaises(UserWarning, warnings.warn, 'hex/oct')
text = 'nonmatching text'
warnings.warn(text)
self.assertEqual(str(w.message), text)
self.assert_(w.category is UserWarning)
def test_options(self):
# Uses the private _setoption() function to test the parsing
# of command-line warning arguments
self.assertRaises(warnings._OptionError,
warnings._setoption, '1:2:3:4:5:6')
self.assertRaises(warnings._OptionError,
warnings._setoption, 'bogus::Warning')
self.assertRaises(warnings._OptionError,
warnings._setoption, 'ignore:2::4:-5')
warnings._setoption('error::Warning::0')
self.assertRaises(UserWarning, warnings.warn, 'convert to error')
with test_support.guard_warnings_filter():
self.assertRaises(warnings._OptionError,
warnings._setoption, '1:2:3:4:5:6')
self.assertRaises(warnings._OptionError,
warnings._setoption, 'bogus::Warning')
self.assertRaises(warnings._OptionError,
warnings._setoption, 'ignore:2::4:-5')
warnings._setoption('error::Warning::0')
self.assertRaises(UserWarning, warnings.warn, 'convert to error')
def test_filename(self):
warning_tests.inner("spam1")
self.assertEqual(msg.filename, "warning_tests.py")
warning_tests.outer("spam2")
self.assertEqual(msg.filename, "warning_tests.py")
with test_support.catch_warning() as w:
warning_tests.inner("spam1")
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
warning_tests.outer("spam2")
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
def test_stacklevel(self):
# Test stacklevel argument
# make sure all messages are different, so the warning won't be skipped
warning_tests.inner("spam3", stacklevel=1)
self.assertEqual(msg.filename, "warning_tests.py")
warning_tests.outer("spam4", stacklevel=1)
self.assertEqual(msg.filename, "warning_tests.py")
with test_support.catch_warning() as w:
warning_tests.inner("spam3", stacklevel=1)
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
warning_tests.outer("spam4", stacklevel=1)
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
warning_tests.inner("spam5", stacklevel=2)
self.assertEqual(msg.filename, "test_warnings.py")
warning_tests.outer("spam6", stacklevel=2)
self.assertEqual(msg.filename, "warning_tests.py")
warning_tests.inner("spam5", stacklevel=2)
self.assertEqual(os.path.basename(w.filename), "test_warnings.py")
warning_tests.outer("spam6", stacklevel=2)
self.assertEqual(os.path.basename(w.filename), "warning_tests.py")
warning_tests.inner("spam7", stacklevel=9999)
self.assertEqual(msg.filename, "sys")
warning_tests.inner("spam7", stacklevel=9999)
self.assertEqual(os.path.basename(w.filename), "sys")
def test_main(verbose=None):

View File

@ -713,6 +713,9 @@ Tests
- Fix bsddb test_basics.test06_Transactions to check the version
number properly.
- test.test_support.catch_warning is a new context manager that can be used
to catch the warnings issued by the warning framework.
Tools
-----