mirror of
				https://github.com/python/cpython.git
				synced 2025-10-26 11:14:33 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			166 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			166 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import os
 | |
| import unittest
 | |
| import collections
 | |
| import email
 | |
| from email.message import Message
 | |
| from email._policybase import compat32
 | |
| from test.support import load_package_tests
 | |
| from test.test_email import __file__ as landmark
 | |
| 
 | |
| # Load all tests in package
 | |
| def load_tests(*args):
 | |
|     return load_package_tests(os.path.dirname(__file__), *args)
 | |
| 
 | |
| 
 | |
| # helper code used by a number of test modules.
 | |
| 
 | |
| def openfile(filename, *args, **kws):
 | |
|     path = os.path.join(os.path.dirname(landmark), 'data', filename)
 | |
|     return open(path, *args, **kws)
 | |
| 
 | |
| 
 | |
| # Base test class
 | |
| class TestEmailBase(unittest.TestCase):
 | |
| 
 | |
|     maxDiff = None
 | |
|     # Currently the default policy is compat32.  By setting that as the default
 | |
|     # here we make minimal changes in the test_email tests compared to their
 | |
|     # pre-3.3 state.
 | |
|     policy = compat32
 | |
|     # Likewise, the default message object is Message.
 | |
|     message = Message
 | |
| 
 | |
|     def __init__(self, *args, **kw):
 | |
|         super().__init__(*args, **kw)
 | |
|         self.addTypeEqualityFunc(bytes, self.assertBytesEqual)
 | |
| 
 | |
|     # Backward compatibility to minimize test_email test changes.
 | |
|     ndiffAssertEqual = unittest.TestCase.assertEqual
 | |
| 
 | |
|     def _msgobj(self, filename):
 | |
|         with openfile(filename, encoding="utf-8") as fp:
 | |
|             return email.message_from_file(fp, policy=self.policy)
 | |
| 
 | |
|     def _str_msg(self, string, message=None, policy=None):
 | |
|         if policy is None:
 | |
|             policy = self.policy
 | |
|         if message is None:
 | |
|             message = self.message
 | |
|         return email.message_from_string(string, message, policy=policy)
 | |
| 
 | |
|     def _bytes_msg(self, bytestring, message=None, policy=None):
 | |
|         if policy is None:
 | |
|             policy = self.policy
 | |
|         if message is None:
 | |
|             message = self.message
 | |
|         return email.message_from_bytes(bytestring, message, policy=policy)
 | |
| 
 | |
|     def _make_message(self):
 | |
|         return self.message(policy=self.policy)
 | |
| 
 | |
|     def _bytes_repr(self, b):
 | |
|         return [repr(x) for x in b.splitlines(keepends=True)]
 | |
| 
 | |
|     def assertBytesEqual(self, first, second, msg):
 | |
|         """Our byte strings are really encoded strings; improve diff output"""
 | |
|         self.assertEqual(self._bytes_repr(first), self._bytes_repr(second))
 | |
| 
 | |
|     def assertDefectsEqual(self, actual, expected):
 | |
|         self.assertEqual(len(actual), len(expected), actual)
 | |
|         for i in range(len(actual)):
 | |
|             self.assertIsInstance(actual[i], expected[i],
 | |
|                                     'item {}'.format(i))
 | |
| 
 | |
| 
 | |
| def parameterize(cls):
 | |
|     """A test method parameterization class decorator.
 | |
| 
 | |
|     Parameters are specified as the value of a class attribute that ends with
 | |
|     the string '_params'.  Call the portion before '_params' the prefix.  Then
 | |
|     a method to be parameterized must have the same prefix, the string
 | |
|     '_as_', and an arbitrary suffix.
 | |
| 
 | |
|     The value of the _params attribute may be either a dictionary or a list.
 | |
|     The values in the dictionary and the elements of the list may either be
 | |
|     single values, or a list.  If single values, they are turned into single
 | |
|     element tuples.  However derived, the resulting sequence is passed via
 | |
|     *args to the parameterized test function.
 | |
| 
 | |
|     In a _params dictionary, the keys become part of the name of the generated
 | |
|     tests.  In a _params list, the values in the list are converted into a
 | |
|     string by joining the string values of the elements of the tuple by '_' and
 | |
|     converting any blanks into '_'s, and this become part of the name.
 | |
|     The  full name of a generated test is a 'test_' prefix, the portion of the
 | |
|     test function name after the  '_as_' separator, plus an '_', plus the name
 | |
|     derived as explained above.
 | |
| 
 | |
|     For example, if we have:
 | |
| 
 | |
|         count_params = range(2)
 | |
| 
 | |
|         def count_as_foo_arg(self, foo):
 | |
|             self.assertEqual(foo+1, myfunc(foo))
 | |
| 
 | |
|     we will get parameterized test methods named:
 | |
|         test_foo_arg_0
 | |
|         test_foo_arg_1
 | |
|         test_foo_arg_2
 | |
| 
 | |
|     Or we could have:
 | |
| 
 | |
|         example_params = {'foo': ('bar', 1), 'bing': ('bang', 2)}
 | |
| 
 | |
|         def example_as_myfunc_input(self, name, count):
 | |
|             self.assertEqual(name+str(count), myfunc(name, count))
 | |
| 
 | |
|     and get:
 | |
|         test_myfunc_input_foo
 | |
|         test_myfunc_input_bing
 | |
| 
 | |
|     Note: if and only if the generated test name is a valid identifier can it
 | |
|     be used to select the test individually from the unittest command line.
 | |
| 
 | |
|     The values in the params dict can be a single value, a tuple, or a
 | |
|     dict.  If a single value of a tuple, it is passed to the test function
 | |
|     as positional arguments.  If a dict, it is a passed via **kw.
 | |
| 
 | |
|     """
 | |
|     paramdicts = {}
 | |
|     testers = collections.defaultdict(list)
 | |
|     for name, attr in cls.__dict__.items():
 | |
|         if name.endswith('_params'):
 | |
|             if not hasattr(attr, 'keys'):
 | |
|                 d = {}
 | |
|                 for x in attr:
 | |
|                     if not hasattr(x, '__iter__'):
 | |
|                         x = (x,)
 | |
|                     n = '_'.join(str(v) for v in x).replace(' ', '_')
 | |
|                     d[n] = x
 | |
|                 attr = d
 | |
|             paramdicts[name[:-7] + '_as_'] = attr
 | |
|         if '_as_' in name:
 | |
|             testers[name.split('_as_')[0] + '_as_'].append(name)
 | |
|     testfuncs = {}
 | |
|     for name in paramdicts:
 | |
|         if name not in testers:
 | |
|             raise ValueError("No tester found for {}".format(name))
 | |
|     for name in testers:
 | |
|         if name not in paramdicts:
 | |
|             raise ValueError("No params found for {}".format(name))
 | |
|     for name, attr in cls.__dict__.items():
 | |
|         for paramsname, paramsdict in paramdicts.items():
 | |
|             if name.startswith(paramsname):
 | |
|                 testnameroot = 'test_' + name[len(paramsname):]
 | |
|                 for paramname, params in paramsdict.items():
 | |
|                     if hasattr(params, 'keys'):
 | |
|                         test = (lambda self, name=name, params=params:
 | |
|                                     getattr(self, name)(**params))
 | |
|                     else:
 | |
|                         test = (lambda self, name=name, params=params:
 | |
|                                         getattr(self, name)(*params))
 | |
|                     testname = testnameroot + '_' + paramname
 | |
|                     test.__name__ = testname
 | |
|                     testfuncs[testname] = test
 | |
|     for key, value in testfuncs.items():
 | |
|         setattr(cls, key, value)
 | |
|     return cls
 | 
