2 # -*- coding: utf-8 -*-
5 # Part of enum, a package providing enumerated types for Python.
7 # Copyright © 2007–2009 Ben Finney <ben+python@benfinney.id.au>
8 # This is free software; you may copy, modify and/or distribute this work
9 # under the terms of the GNU General Public License, version 2 or later
10 # or, at your option, the terms of the Python license.
12 """ Unit test for ‘enum’ module.
19 from deprecated_enum
.test
import tools
21 import deprecated_enum
as enum
24 class Mock_Enum(object):
25 """ Mock object for Enum testing. """
27 def __init__(self
, *keys
):
28 """ Set up a new instance. """
32 def setup_enum_value_fixtures(testcase
):
33 """ Set up fixtures for test cases using ‘EnumValue’. """
36 None, 0, 1, (), Mock_Enum(),
37 enum
.EnumValue(Mock_Enum(), 0, 'bogus'),
40 testcase
.other_values
= [
41 None, 0, 1, (), Mock_Enum(), "bogus",
42 enum
.EnumValue(Mock_Enum(), 0, 'bogus'),
46 ('mercury', "Mercury"),
50 ('jupiter', "Jupiter"),
53 ('neptune', "Neptune"),
55 planet_keys
= [key
for (key
, name
) in testcase
.planets
]
58 'red', 'green', 'blue',
59 'yellow', 'orange', 'purple',
63 simple_keys
= ['spam', 'eggs', 'beans']
64 testcase
.SimpleEnum
= testcase
.enum_factory_class(*simple_keys
)
66 Colour
= testcase
.enum_factory_class(*colour_keys
)
67 Planet
= testcase
.enum_factory_class(*planet_keys
)
68 testcase
.valid_values
= {
77 for enumtype
, params
in testcase
.valid_values
.items():
78 params
['enumtype'] = enumtype
80 for i
, key
in enumerate(params
['keys']):
81 values
[key
] = enum
.EnumValue(enumtype
, i
, key
)
82 params
['values'] = values
85 class Test_Module(unittest
.TestCase
):
86 """ Test case for the module. """
89 """ Set up test fixtures. """
90 from sys
import modules
91 self
.module
= modules
['deprecated_enum']
93 def test_author_name_is_string(self
):
94 """ Module should have __author_name__ string. """
95 mod_author_name
= self
.module
.__author
_name
__
96 self
.failUnless(isinstance(mod_author_name
, basestring
))
98 def test_author_email_is_string(self
):
99 """ Module should have __author_email__ string. """
100 mod_author_email
= self
.module
.__author
_email
__
101 self
.failUnless(isinstance(mod_author_email
, basestring
))
103 def test_author_is_string(self
):
104 """ Module should have __author__ string. """
105 mod_author
= self
.module
.__author
__
106 self
.failUnless(isinstance(mod_author
, basestring
))
108 def test_author_contains_name(self
):
109 """ Module __author__ string should contain author name. """
110 mod_author
= self
.module
.__author
__
111 mod_author_name
= self
.module
.__author
_name
__
112 self
.failUnless(mod_author
.startswith(mod_author_name
))
114 def test_author_contains_email(self
):
115 """ Module __author__ string should contain author email. """
116 mod_author
= self
.module
.__author
__
117 mod_author_email
= self
.module
.__author
_email
__
118 self
.failUnless(mod_author
.endswith("<%(mod_author_email)s>" % vars()))
120 def test_date_is_string(self
):
121 """ Module should have __date__ string. """
122 mod_date
= self
.module
.__date
__
123 self
.failUnless(isinstance(mod_date
, basestring
))
125 def test_copyright_is_string(self
):
126 """ Module should have __copyright__ string. """
127 mod_copyright
= self
.module
.__copyright
__
128 self
.failUnless(isinstance(mod_copyright
, basestring
))
130 def test_copyright_contains_name(self
):
131 """ Module __copyright__ string should contain author name. """
132 mod_copyright
= self
.module
.__copyright
__
133 mod_author_name
= self
.module
.__author
_name
__
134 self
.failUnless(mod_copyright
.endswith(mod_author_name
))
136 def test_copyright_contains_begin_year(self
):
137 """ Module __copyright__ string should contain beginning year. """
138 mod_copyright
= self
.module
.__copyright
__
139 year_begin
= self
.module
._copyright
_year
_begin
140 self
.failUnless(year_begin
in mod_copyright
)
142 def test_copyright_contains_latest_year(self
):
143 """ Module __copyright__ string should contain latest year.. """
144 mod_copyright
= self
.module
.__copyright
__
145 year_latest
= self
.module
.__date
__.split('-')[0]
146 self
.failUnless(year_latest
in mod_copyright
)
148 def test_license_is_string(self
):
149 """ Module should have __license__ string. """
150 mod_license
= self
.module
.__license
__
151 self
.failUnless(isinstance(mod_license
, basestring
))
153 def test_url_is_string(self
):
154 """ Module should have __url__ string. """
155 mod_url
= self
.module
.__url
__
156 self
.failUnless(isinstance(mod_url
, basestring
))
158 def test_version_is_string(self
):
159 """ Module should have __version__ string. """
160 mod_version
= self
.module
.__version
__
161 self
.failUnless(isinstance(mod_version
, basestring
))
164 class Test_EnumException(unittest
.TestCase
):
165 """ Test case for the Enum exception classes. """
168 """ Set up test fixtures. """
169 self
.valid_exceptions
= {
170 enum
.EnumEmptyError
: dict(
172 types
= (enum
.EnumException
, AssertionError),
174 enum
.EnumBadKeyError
: dict(
176 types
= (enum
.EnumException
, TypeError),
178 enum
.EnumImmutableError
: dict(
180 types
= (enum
.EnumException
, TypeError),
184 for exc_type
, params
in self
.valid_exceptions
.items():
185 args
= (None,) * params
['min_args']
186 instance
= exc_type(*args
)
187 self
.valid_exceptions
[exc_type
]['instance'] = instance
189 def test_EnumException_abstract(self
):
190 """ The module exception base class should be abstract. """
191 self
.failUnlessRaises(
192 NotImplementedError, enum
.EnumException
)
194 def test_exception_instance(self
):
195 """ Exception instance should be created. """
196 for exc_type
, params
in self
.valid_exceptions
.items():
197 instance
= params
['instance']
198 self
.failUnless(instance
)
200 def test_exception_types(self
):
201 """ Exception instances should match expected types. """
202 for exc_type
, params
in self
.valid_exceptions
.items():
203 instance
= params
['instance']
204 for match_type
in params
['types']:
206 isinstance(instance
, match_type
),
208 "instance: %(instance)r, match_type: %(match_type)s"
212 compare_functions
= [
213 getattr(operator
, name
)
214 for name
in ['__eq__', '__ne__', '__lt__', '__le__', '__gt__', '__ge__']]
216 class Test_EnumValue(unittest
.TestCase
):
217 """ Test case for the EnumValue class. """
219 enum_factory_class
= Mock_Enum
222 """ Set up the test fixtures. """
223 setup_enum_value_fixtures(self
)
225 def test_instantiate(self
):
226 """ Creating an EnumValue instance should succeed. """
227 for enumtype
, params
in self
.valid_values
.items():
228 for key
, instance
in params
['values'].items():
229 self
.failUnless(instance
)
231 def test_enumtype_equal(self
):
232 """ EnumValue should export its enum type. """
233 for enumtype
, params
in self
.valid_values
.items():
234 for key
, instance
in params
['values'].items():
235 self
.failUnlessEqual(enumtype
, instance
.enumtype
)
237 def test_key_equal(self
):
238 """ EnumValue should export its string key. """
239 for enumtype
, params
in self
.valid_values
.items():
240 for key
, instance
in params
['values'].items():
241 self
.failUnlessEqual(key
, instance
.key
)
243 def test_str_key(self
):
244 """ String value for EnumValue should be its key string. """
245 for enumtype
, params
in self
.valid_values
.items():
246 for key
, instance
in params
['values'].items():
247 self
.failUnlessEqual(key
, str(instance
))
249 def test_index_equal(self
):
250 """ EnumValue should export its sequence index. """
251 for enumtype
, params
in self
.valid_values
.items():
252 for i
, key
in enumerate(params
['keys']):
253 instance
= params
['values'][key
]
254 self
.failUnlessEqual(i
, instance
.index
)
257 """ Representation of EnumValue should be meaningful. """
258 for enumtype
, params
in self
.valid_values
.items():
259 for i
, key
in enumerate(params
['keys']):
260 instance
= params
['values'][key
]
261 repr_str
= repr(instance
)
262 self
.failUnless(repr_str
.startswith('EnumValue('))
263 self
.failUnless(repr_str
.count(repr(enumtype
)))
264 self
.failUnless(repr_str
.count(repr(i
)))
265 self
.failUnless(repr_str
.count(repr(key
)))
266 self
.failUnless(repr_str
.endswith(')'))
268 def test_hash_equal(self
):
269 """ Each EnumValue instance should have same hash as its value. """
270 for enumtype
, params
in self
.valid_values
.items():
271 for i
, key
in enumerate(params
['keys']):
272 instance
= params
['values'][key
]
273 self
.failUnlessEqual(hash(i
), hash(instance
))
275 def test_hash_unequal(self
):
276 """ Different EnumValue instances should have different hashes. """
277 for enumtype
, params
in self
.valid_values
.items():
278 for i
, key
in enumerate(params
['keys']):
279 instance
= params
['values'][key
]
280 for j
, other_key
in enumerate(params
['keys']):
283 other_instance
= params
['values'][other_key
]
285 hash(instance
), hash(other_instance
))
287 def test_comparison_method_has_matching_name(self
):
288 """ Comparison method should have matching name for attribute. """
289 for compare_func
in compare_functions
:
290 func_name
= compare_func
.__name
__
291 expect_name
= func_name
292 compare_method
= getattr(enum
.EnumValue
, func_name
)
293 self
.failUnlessEqual(
294 expect_name
, compare_method
.__name
__)
296 def test_comparison_method_has_docstring(self
):
297 """ Comparison method should have docstring. """
298 for compare_func
in compare_functions
:
299 func_name
= compare_func
.__name
__
300 compare_method
= getattr(enum
.EnumValue
, func_name
)
302 isinstance(compare_method
.__doc
__, basestring
))
304 def test_compare_equal(self
):
305 """ An EnumValue should compare equal to its value. """
306 for enumtype
, params
in self
.valid_values
.items():
307 for i
, key
in enumerate(params
['keys']):
308 instance
= params
['values'][key
]
309 self
.failUnlessEqual(
310 instance
, enum
.EnumValue(enumtype
, i
, key
))
312 def test_compare_unequal(self
):
313 """ An EnumValue should compare different to other values. """
314 for enumtype
, params
in self
.valid_values
.items():
315 for i
, key
in enumerate(params
['keys']):
316 instance
= params
['values'][key
]
319 enum
.EnumValue(enumtype
, None, None))
321 def test_compare_sequence(self
):
322 """ EnumValue instances should compare as their sequence order. """
323 for enumtype
, params
in self
.valid_values
.items():
324 for i
, left_key
in enumerate(params
['keys']):
325 for j
, right_key
in enumerate(params
['keys']):
326 for compare_func
in compare_functions
:
327 self
.failUnlessEqual(
329 compare_func(params
['values'][left_key
],
330 enum
.EnumValue(enumtype
, j
, right_key
))
333 def test_compare_different_enum(self
):
334 """ An EnumValue should not implement comparison to other enums. """
335 for enumtype
, params
in self
.valid_values
.items():
336 for i
, key
in enumerate(params
['keys']):
337 for compare_func
in compare_functions
:
338 instance
= params
['values'][key
]
339 test_value
= enum
.EnumValue(self
.SimpleEnum
, i
, key
)
340 compare_method
= getattr(instance
, compare_func
.__name
__)
341 compare_result
= compare_method(test_value
)
342 self
.failUnlessEqual(NotImplemented, compare_result
)
344 def test_compare_non_enum(self
):
345 """ An EnumValue should not implement comparison to other types. """
346 test_value
= enum
.EnumValue(self
.SimpleEnum
, 0, 'test')
347 for other_value
in self
.other_values
:
348 for compare_func
in compare_functions
:
349 compare_method
= getattr(test_value
, compare_func
.__name
__)
350 compare_result
= compare_method(other_value
)
351 self
.failUnlessEqual(NotImplemented, compare_result
)
353 def test_compare_equality_different_enum(self
):
354 """ An EnumValue should compare inequal to values of other enums. """
355 for enumtype
, params
in self
.valid_values
.items():
356 for i
, key
in enumerate(params
['keys']):
357 instance
= params
['values'][key
]
358 test_value
= enum
.EnumValue(self
.SimpleEnum
, i
, key
)
359 self
.failIfEqual(test_value
, instance
)
361 def test_compare_equality_non_enum(self
):
362 """ An EnumValue should compare inequal to any other value. """
363 test_value
= enum
.EnumValue(self
.SimpleEnum
, 0, 'test')
364 for other_value
in self
.other_values
:
365 self
.failIfEqual(test_value
, other_value
)
367 def test_sequence_other_values(self
):
368 """ An EnumValue should compare sequentially to other values. """
369 test_value
= enum
.EnumValue(self
.SimpleEnum
, 0, 'test')
370 test_list
= list(self
.other_values
)
371 test_list
.append(test_value
)
373 self
.failUnless(test_value
in test_list
)
375 def test_value_key(self
):
376 """ An EnumValue should have the specified key. """
377 for enumtype
, params
in self
.valid_values
.items():
378 for key
, instance
in params
['values'].items():
379 self
.failUnlessEqual(key
, instance
.key
)
381 def test_value_enumtype(self
):
382 """ An EnumValue should have its associated enumtype. """
383 for enumtype
, params
in self
.valid_values
.items():
384 for key
, instance
in params
['values'].items():
385 self
.failUnlessEqual(enumtype
, instance
.enumtype
)
388 class Test_Enum(unittest
.TestCase
):
389 """ Test case for the Enum class. """
391 enum_factory_class
= enum
.Enum
394 """ Set up the test fixtures. """
395 setup_enum_value_fixtures(self
)
397 def test_empty_enum(self
):
398 """ Enum constructor should refuse empty keys sequence. """
399 self
.failUnlessRaises(
403 def test_bad_key(self
):
404 """ Enum constructor should refuse non-string keys. """
405 for key
in self
.bad_keys
:
406 args
= ("valid", key
, "valid")
407 self
.failUnlessRaises(
408 enum
.EnumBadKeyError
,
411 def test_value_attributes(self
):
412 """ Enumeration should have attributes for each value. """
413 for enumtype
, params
in self
.valid_values
.items():
414 for i
, key
in enumerate(params
['keys']):
415 instance
= getattr(enumtype
, key
)
416 test_value
= enum
.EnumValue(enumtype
, i
, key
)
417 self
.failUnlessEqual(test_value
, instance
)
419 def test_length(self
):
420 """ Enumeration should have length of its value set. """
421 for enumtype
, params
in self
.valid_values
.items():
422 self
.failUnlessEqual(len(params
['values']), len(enumtype
))
424 def test_value_items(self
):
425 """ Enumeration should have items for each value. """
426 for enumtype
, params
in self
.valid_values
.items():
427 for i
, key
in enumerate(params
['keys']):
429 test_value
= enum
.EnumValue(enumtype
, i
, key
)
430 self
.failUnlessEqual(test_value
, value
)
432 def test_iterable(self
):
433 """ Enumeration class should iterate over its values. """
434 for enumtype
, params
in self
.valid_values
.items():
435 for i
, value
in enumerate(enumtype
):
436 key
= params
['keys'][i
]
437 test_value
= params
['values'][key
]
438 self
.failUnlessEqual(value
, test_value
)
440 def test_iterate_sequence(self
):
441 """ Enumeration iteration should match specified sequence. """
442 for enumtype
, params
in self
.valid_values
.items():
443 values_dict
= params
['values']
444 values_seq
= [values_dict
[key
] for key
in params
['keys']]
445 enum_seq
= [val
for val
in enumtype
]
446 self
.failUnlessEqual(values_seq
, enum_seq
)
447 self
.failIfEqual(values_seq
.reverse(), enum_seq
)
449 def test_membership_bogus(self
):
450 """ Enumeration should not contain bogus values. """
451 for enumtype
, params
in self
.valid_values
.items():
452 for value
in self
.other_values
:
453 self
.failIf(value
in enumtype
)
455 def test_membership_value(self
):
456 """ Enumeration should contain explicit value. """
457 for enumtype
, params
in self
.valid_values
.items():
458 for i
, key
in enumerate(params
['keys']):
459 value
= params
['values'][key
]
460 self
.failUnless(value
in enumtype
)
462 def test_membership_key(self
):
463 """ Enumeration should contain key string. """
464 for enumtype
, params
in self
.valid_values
.items():
465 for key
in params
['keys']:
466 self
.failUnless(key
in enumtype
)
468 def test_add_attribute(self
):
469 """ Enumeration should refuse attribute addition. """
470 for enumtype
, params
in self
.valid_values
.items():
471 self
.failUnlessRaises(
472 enum
.EnumImmutableError
,
473 setattr, enumtype
, 'bogus', "bogus")
475 def test_modify_attribute(self
):
476 """ Enumeration should refuse attribute modification. """
477 for enumtype
, params
in self
.valid_values
.items():
478 for key
in params
['keys']:
479 self
.failUnlessRaises(
480 enum
.EnumImmutableError
,
481 setattr, enumtype
, key
, "bogus")
483 def test_delete_attribute(self
):
484 """ Enumeration should refuse attribute deletion. """
485 for enumtype
, params
in self
.valid_values
.items():
486 for key
in params
['keys']:
487 self
.failUnlessRaises(
488 enum
.EnumImmutableError
,
489 delattr, enumtype
, key
)
491 def test_add_item(self
):
492 """ Enumeration should refuse item addition. """
493 for enumtype
, params
in self
.valid_values
.items():
494 index
= len(params
['keys'])
495 self
.failUnlessRaises(
496 enum
.EnumImmutableError
,
497 enumtype
.__setitem
__, index
, "bogus")
499 def test_modify_item(self
):
500 """ Enumeration should refuse item modification. """
501 for enumtype
, params
in self
.valid_values
.items():
502 for i
, key
in enumerate(params
['keys']):
503 self
.failUnlessRaises(
504 enum
.EnumImmutableError
,
505 enumtype
.__setitem
__, i
, "bogus")
507 def test_delete_item(self
):
508 """ Enumeration should refuse item deletion. """
509 for enumtype
, params
in self
.valid_values
.items():
510 for i
, key
in enumerate(params
['keys']):
511 self
.failUnlessRaises(
512 enum
.EnumImmutableError
,
513 enumtype
.__delitem
__, i
)
517 """ Create the test suite for this module. """
518 from sys
import modules
519 loader
= unittest
.TestLoader()
520 suite
= loader
.loadTestsFromModule(modules
[__name__
])
524 def __main__(argv
=None):
525 """ Mainline function for this module. """
532 unittest
.main(argv
=argv
, defaultTest
='suite')
533 except SystemExit, exc
:
538 if __name__
== '__main__':
540 exitcode
= __main__(sys
.argv
)
547 # vim: filetype=python fileencoding=utf-8 :