OLD | NEW |
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. | 2 # copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
3 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr | 3 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr |
4 # | 4 # |
5 # This file is part of logilab-common. | 5 # This file is part of logilab-common. |
6 # | 6 # |
7 # logilab-common is free software: you can redistribute it and/or modify it unde
r | 7 # logilab-common is free software: you can redistribute it and/or modify it unde
r |
8 # the terms of the GNU Lesser General Public License as published by the Free | 8 # the terms of the GNU Lesser General Public License as published by the Free |
9 # Software Foundation, either version 2.1 of the License, or (at your option) an
y | 9 # Software Foundation, either version 2.1 of the License, or (at your option) an
y |
10 # later version. | 10 # later version. |
11 # | 11 # |
12 # logilab-common is distributed in the hope that it will be useful, but WITHOUT | 12 # logilab-common is distributed in the hope that it will be useful, but WITHOUT |
(...skipping 16 matching lines...) Expand all Loading... |
29 -t testdir -- directory where the tests will be found | 29 -t testdir -- directory where the tests will be found |
30 -x exclude -- add a test to exclude | 30 -x exclude -- add a test to exclude |
31 -p profile -- profiled execution | 31 -p profile -- profiled execution |
32 -d dbc -- enable design-by-contract | 32 -d dbc -- enable design-by-contract |
33 -m match -- only run test matching the tag pattern which follow | 33 -m match -- only run test matching the tag pattern which follow |
34 | 34 |
35 If no non-option arguments are present, prefixes used are 'test', | 35 If no non-option arguments are present, prefixes used are 'test', |
36 'regrtest', 'smoketest' and 'unittest'. | 36 'regrtest', 'smoketest' and 'unittest'. |
37 | 37 |
38 """ | 38 """ |
| 39 |
| 40 from __future__ import print_function |
| 41 |
39 __docformat__ = "restructuredtext en" | 42 __docformat__ = "restructuredtext en" |
40 # modified copy of some functions from test/regrtest.py from PyXml | 43 # modified copy of some functions from test/regrtest.py from PyXml |
41 # disable camel case warning | 44 # disable camel case warning |
42 # pylint: disable=C0103 | 45 # pylint: disable=C0103 |
43 | 46 |
44 import sys | 47 import sys |
45 import os, os.path as osp | 48 import os, os.path as osp |
46 import re | 49 import re |
47 import traceback | 50 import traceback |
48 import inspect | 51 import inspect |
49 import difflib | 52 import difflib |
50 import tempfile | 53 import tempfile |
51 import math | 54 import math |
52 import warnings | 55 import warnings |
53 from shutil import rmtree | 56 from shutil import rmtree |
54 from operator import itemgetter | 57 from operator import itemgetter |
55 from ConfigParser import ConfigParser | 58 from itertools import dropwhile |
| 59 from inspect import isgeneratorfunction |
| 60 |
| 61 from six import string_types |
| 62 from six.moves import builtins, range, configparser, input |
| 63 |
56 from logilab.common.deprecation import deprecated | 64 from logilab.common.deprecation import deprecated |
57 from itertools import dropwhile | |
58 | 65 |
59 import unittest as unittest_legacy | 66 import unittest as unittest_legacy |
60 if not getattr(unittest_legacy, "__package__", None): | 67 if not getattr(unittest_legacy, "__package__", None): |
61 try: | 68 try: |
62 import unittest2 as unittest | 69 import unittest2 as unittest |
63 from unittest2 import SkipTest | 70 from unittest2 import SkipTest |
64 except ImportError: | 71 except ImportError: |
65 sys.exit("You have to install python-unittest2 to use this module") | 72 raise ImportError("You have to install python-unittest2 to use %s" % __n
ame__) |
66 else: | 73 else: |
67 import unittest | 74 import unittest |
68 from unittest import SkipTest | 75 from unittest import SkipTest |
69 | 76 |
70 try: | 77 from functools import wraps |
71 from functools import wraps | |
72 except ImportError: | |
73 def wraps(wrapped): | |
74 def proxy(callable): | |
75 callable.__name__ = wrapped.__name__ | |
76 return callable | |
77 return proxy | |
78 try: | |
79 from test import test_support | |
80 except ImportError: | |
81 # not always available | |
82 class TestSupport: | |
83 def unload(self, test): | |
84 pass | |
85 test_support = TestSupport() | |
86 | 78 |
87 # pylint: disable=W0622 | |
88 from logilab.common.compat import any, InheritableSet, callable | |
89 # pylint: enable=W0622 | |
90 from logilab.common.debugger import Debugger, colorize_source | 79 from logilab.common.debugger import Debugger, colorize_source |
91 from logilab.common.decorators import cached, classproperty | 80 from logilab.common.decorators import cached, classproperty |
92 from logilab.common import textutils | 81 from logilab.common import textutils |
93 | 82 |
94 | 83 |
95 __all__ = ['main', 'unittest_main', 'find_tests', 'run_test', 'spawn'] | 84 __all__ = ['main', 'unittest_main', 'find_tests', 'run_test', 'spawn'] |
96 | 85 |
97 DEFAULT_PREFIXES = ('test', 'regrtest', 'smoketest', 'unittest', | 86 DEFAULT_PREFIXES = ('test', 'regrtest', 'smoketest', 'unittest', |
98 'func', 'validation') | 87 'func', 'validation') |
99 | 88 |
100 | 89 is_generator = deprecated('[lgc 0.63] use inspect.isgeneratorfunction')(isgenera
torfunction) |
101 if sys.version_info >= (2, 6): | |
102 # FIXME : this does not work as expected / breaks tests on testlib | |
103 # however testlib does not work on py3k for many reasons ... | |
104 from inspect import CO_GENERATOR | |
105 else: | |
106 from compiler.consts import CO_GENERATOR | |
107 | |
108 if sys.version_info >= (3, 0): | |
109 def is_generator(function): | |
110 flags = function.__code__.co_flags | |
111 return flags & CO_GENERATOR | |
112 | |
113 else: | |
114 def is_generator(function): | |
115 flags = function.func_code.co_flags | |
116 return flags & CO_GENERATOR | |
117 | 90 |
118 # used by unittest to count the number of relevant levels in the traceback | 91 # used by unittest to count the number of relevant levels in the traceback |
119 __unittest = 1 | 92 __unittest = 1 |
120 | 93 |
121 | 94 |
122 def with_tempdir(callable): | 95 def with_tempdir(callable): |
123 """A decorator ensuring no temporary file left when the function return | 96 """A decorator ensuring no temporary file left when the function return |
124 Work only for temporary file create with the tempfile module""" | 97 Work only for temporary file create with the tempfile module""" |
| 98 if isgeneratorfunction(callable): |
| 99 def proxy(*args, **kwargs): |
| 100 old_tmpdir = tempfile.gettempdir() |
| 101 new_tmpdir = tempfile.mkdtemp(prefix="temp-lgc-") |
| 102 tempfile.tempdir = new_tmpdir |
| 103 try: |
| 104 for x in callable(*args, **kwargs): |
| 105 yield x |
| 106 finally: |
| 107 try: |
| 108 rmtree(new_tmpdir, ignore_errors=True) |
| 109 finally: |
| 110 tempfile.tempdir = old_tmpdir |
| 111 return proxy |
| 112 |
125 @wraps(callable) | 113 @wraps(callable) |
126 def proxy(*args, **kargs): | 114 def proxy(*args, **kargs): |
127 | 115 |
128 old_tmpdir = tempfile.gettempdir() | 116 old_tmpdir = tempfile.gettempdir() |
129 new_tmpdir = tempfile.mkdtemp(prefix="temp-lgc-") | 117 new_tmpdir = tempfile.mkdtemp(prefix="temp-lgc-") |
130 tempfile.tempdir = new_tmpdir | 118 tempfile.tempdir = new_tmpdir |
131 try: | 119 try: |
132 return callable(*args, **kargs) | 120 return callable(*args, **kargs) |
133 finally: | 121 finally: |
134 try: | 122 try: |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 """starts an interactive shell so that the user can inspect errors | 171 """starts an interactive shell so that the user can inspect errors |
184 """ | 172 """ |
185 debuggers = result.debuggers | 173 debuggers = result.debuggers |
186 descrs = result.error_descrs + result.fail_descrs | 174 descrs = result.error_descrs + result.fail_descrs |
187 if len(debuggers) == 1: | 175 if len(debuggers) == 1: |
188 # don't ask for test name if there's only one failure | 176 # don't ask for test name if there's only one failure |
189 debuggers[0].start() | 177 debuggers[0].start() |
190 else: | 178 else: |
191 while True: | 179 while True: |
192 testindex = 0 | 180 testindex = 0 |
193 print "Choose a test to debug:" | 181 print("Choose a test to debug:") |
194 # order debuggers in the same way than errors were printed | 182 # order debuggers in the same way than errors were printed |
195 print "\n".join(['\t%s : %s' % (i, descr) for i, (_, descr) | 183 print("\n".join(['\t%s : %s' % (i, descr) for i, (_, descr) |
196 in enumerate(descrs)]) | 184 in enumerate(descrs)])) |
197 print "Type 'exit' (or ^D) to quit" | 185 print("Type 'exit' (or ^D) to quit") |
198 print | 186 print() |
199 try: | 187 try: |
200 todebug = raw_input('Enter a test name: ') | 188 todebug = input('Enter a test name: ') |
201 if todebug.strip().lower() == 'exit': | 189 if todebug.strip().lower() == 'exit': |
202 print | 190 print() |
203 break | 191 break |
204 else: | 192 else: |
205 try: | 193 try: |
206 testindex = int(todebug) | 194 testindex = int(todebug) |
207 debugger = debuggers[descrs[testindex][0]] | 195 debugger = debuggers[descrs[testindex][0]] |
208 except (ValueError, IndexError): | 196 except (ValueError, IndexError): |
209 print "ERROR: invalid test number %r" % (todebug, ) | 197 print("ERROR: invalid test number %r" % (todebug, )) |
210 else: | 198 else: |
211 debugger.start() | 199 debugger.start() |
212 except (EOFError, KeyboardInterrupt): | 200 except (EOFError, KeyboardInterrupt): |
213 print | 201 print() |
214 break | 202 break |
215 | 203 |
216 | 204 |
217 # test utils ################################################################## | 205 # test utils ################################################################## |
218 | 206 |
219 class SkipAwareTestResult(unittest._TextTestResult): | 207 class SkipAwareTestResult(unittest._TextTestResult): |
220 | 208 |
221 def __init__(self, stream, descriptions, verbosity, | 209 def __init__(self, stream, descriptions, verbosity, |
222 exitfirst=False, pdbmode=False, cvg=None, colorize=False): | 210 exitfirst=False, pdbmode=False, cvg=None, colorize=False): |
223 super(SkipAwareTestResult, self).__init__(stream, | 211 super(SkipAwareTestResult, self).__init__(stream, |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
357 # add testlib specific deprecation warning and switch to new api | 345 # add testlib specific deprecation warning and switch to new api |
358 if hasattr(module, 'teardown_module'): | 346 if hasattr(module, 'teardown_module'): |
359 warnings.warn('Please rename teardown_module() to tearDownModule() inste
ad.', | 347 warnings.warn('Please rename teardown_module() to tearDownModule() inste
ad.', |
360 DeprecationWarning) | 348 DeprecationWarning) |
361 setattr(module, 'tearDownModule', module.teardown_module) | 349 setattr(module, 'tearDownModule', module.teardown_module) |
362 # end of monkey-patching | 350 # end of monkey-patching |
363 tearDownModule = getattr(module, 'tearDownModule', None) | 351 tearDownModule = getattr(module, 'tearDownModule', None) |
364 if tearDownModule is not None: | 352 if tearDownModule is not None: |
365 try: | 353 try: |
366 tearDownModule() | 354 tearDownModule() |
367 except Exception, e: | 355 except Exception as e: |
368 if isinstance(result, _DebugResult): | 356 if isinstance(result, _DebugResult): |
369 raise | 357 raise |
370 errorName = 'tearDownModule (%s)' % previousModule | 358 errorName = 'tearDownModule (%s)' % previousModule |
371 self._addClassOrModuleLevelException(result, e, errorName) | 359 self._addClassOrModuleLevelException(result, e, errorName) |
372 | 360 |
373 @monkeypatch(unittest.TestSuite) | 361 @monkeypatch(unittest.TestSuite) |
374 def _handleModuleFixture(self, test, result): | 362 def _handleModuleFixture(self, test, result): |
375 previousModule = self._get_previous_module(result) | 363 previousModule = self._get_previous_module(result) |
376 currentModule = test.__class__.__module__ | 364 currentModule = test.__class__.__module__ |
377 if currentModule == previousModule: | 365 if currentModule == previousModule: |
378 return | 366 return |
379 self._handleModuleTearDown(result) | 367 self._handleModuleTearDown(result) |
380 result._moduleSetUpFailed = False | 368 result._moduleSetUpFailed = False |
381 try: | 369 try: |
382 module = sys.modules[currentModule] | 370 module = sys.modules[currentModule] |
383 except KeyError: | 371 except KeyError: |
384 return | 372 return |
385 # add testlib specific deprecation warning and switch to new api | 373 # add testlib specific deprecation warning and switch to new api |
386 if hasattr(module, 'setup_module'): | 374 if hasattr(module, 'setup_module'): |
387 warnings.warn('Please rename setup_module() to setUpModule() instead.', | 375 warnings.warn('Please rename setup_module() to setUpModule() instead.', |
388 DeprecationWarning) | 376 DeprecationWarning) |
389 setattr(module, 'setUpModule', module.setup_module) | 377 setattr(module, 'setUpModule', module.setup_module) |
390 # end of monkey-patching | 378 # end of monkey-patching |
391 setUpModule = getattr(module, 'setUpModule', None) | 379 setUpModule = getattr(module, 'setUpModule', None) |
392 if setUpModule is not None: | 380 if setUpModule is not None: |
393 try: | 381 try: |
394 setUpModule() | 382 setUpModule() |
395 except Exception, e: | 383 except Exception as e: |
396 if isinstance(result, _DebugResult): | 384 if isinstance(result, _DebugResult): |
397 raise | 385 raise |
398 result._moduleSetUpFailed = True | 386 result._moduleSetUpFailed = True |
399 errorName = 'setUpModule (%s)' % currentModule | 387 errorName = 'setUpModule (%s)' % currentModule |
400 self._addClassOrModuleLevelException(result, e, errorName) | 388 self._addClassOrModuleLevelException(result, e, errorName) |
401 | 389 |
402 # backward compatibility: TestSuite might be imported from lgc.testlib | 390 # backward compatibility: TestSuite might be imported from lgc.testlib |
403 TestSuite = unittest.TestSuite | 391 TestSuite = unittest.TestSuite |
404 | 392 |
405 class keywords(dict): | 393 class keywords(dict): |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 | 429 |
442 return args, kwargs | 430 return args, kwargs |
443 | 431 |
444 | 432 |
445 class InnerTest(tuple): | 433 class InnerTest(tuple): |
446 def __new__(cls, name, *data): | 434 def __new__(cls, name, *data): |
447 instance = tuple.__new__(cls, data) | 435 instance = tuple.__new__(cls, data) |
448 instance.name = name | 436 instance.name = name |
449 return instance | 437 return instance |
450 | 438 |
451 class Tags(InheritableSet): # 2.4 compat | 439 class Tags(set): |
452 """A set of tag able validate an expression""" | 440 """A set of tag able validate an expression""" |
453 | 441 |
454 def __init__(self, *tags, **kwargs): | 442 def __init__(self, *tags, **kwargs): |
455 self.inherit = kwargs.pop('inherit', True) | 443 self.inherit = kwargs.pop('inherit', True) |
456 if kwargs: | 444 if kwargs: |
457 raise TypeError("%s are an invalid keyword argument for this function
" % kwargs.keys()) | 445 raise TypeError("%s are an invalid keyword argument for this function
" % kwargs.keys()) |
458 | 446 |
459 if len(tags) == 1 and not isinstance(tags[0], basestring): | 447 if len(tags) == 1 and not isinstance(tags[0], string_types): |
460 tags = tags[0] | 448 tags = tags[0] |
461 super(Tags, self).__init__(tags, **kwargs) | 449 super(Tags, self).__init__(tags, **kwargs) |
462 | 450 |
463 def __getitem__(self, key): | 451 def __getitem__(self, key): |
464 return key in self | 452 return key in self |
465 | 453 |
466 def match(self, exp): | 454 def match(self, exp): |
467 return eval(exp, {}, self) | 455 return eval(exp, {}, self) |
468 | 456 |
469 | 457 |
470 # duplicate definition from unittest2 of the _deprecate decorator | 458 # duplicate definition from unittest2 of the _deprecate decorator |
471 def _deprecate(original_func): | 459 def _deprecate(original_func): |
472 def deprecated_func(*args, **kwargs): | 460 def deprecated_func(*args, **kwargs): |
473 warnings.warn( | 461 warnings.warn( |
474 ('Please use %s instead.' % original_func.__name__), | 462 ('Please use %s instead.' % original_func.__name__), |
475 DeprecationWarning, 2) | 463 DeprecationWarning, 2) |
476 return original_func(*args, **kwargs) | 464 return original_func(*args, **kwargs) |
477 return deprecated_func | 465 return deprecated_func |
478 | 466 |
479 class TestCase(unittest.TestCase): | 467 class TestCase(unittest.TestCase): |
480 """A unittest.TestCase extension with some additional methods.""" | 468 """A unittest.TestCase extension with some additional methods.""" |
481 maxDiff = None | 469 maxDiff = None |
482 pdbclass = Debugger | 470 pdbclass = Debugger |
483 tags = Tags() | 471 tags = Tags() |
484 | 472 |
485 def __init__(self, methodName='runTest'): | 473 def __init__(self, methodName='runTest'): |
486 super(TestCase, self).__init__(methodName) | 474 super(TestCase, self).__init__(methodName) |
487 # internal API changed in python2.4 and needed by DocTestCase | 475 self.__exc_info = sys.exc_info |
488 if sys.version_info >= (2, 4): | 476 self.__testMethodName = self._testMethodName |
489 self.__exc_info = sys.exc_info | |
490 self.__testMethodName = self._testMethodName | |
491 else: | |
492 # let's give easier access to _testMethodName to every subclasses | |
493 if hasattr(self, "__testMethodName"): | |
494 self._testMethodName = self.__testMethodName | |
495 self._current_test_descr = None | 477 self._current_test_descr = None |
496 self._options_ = None | 478 self._options_ = None |
497 | 479 |
498 @classproperty | 480 @classproperty |
499 @cached | 481 @cached |
500 def datadir(cls): # pylint: disable=E0213 | 482 def datadir(cls): # pylint: disable=E0213 |
501 """helper attribute holding the standard test's data directory | 483 """helper attribute holding the standard test's data directory |
502 | 484 |
503 NOTE: this is a logilab's standard | 485 NOTE: this is a logilab's standard |
504 """ | 486 """ |
(...skipping 21 matching lines...) Expand all Loading... |
526 """ | 508 """ |
527 if self._current_test_descr is not None: | 509 if self._current_test_descr is not None: |
528 return self._current_test_descr | 510 return self._current_test_descr |
529 return super(TestCase, self).shortDescription() | 511 return super(TestCase, self).shortDescription() |
530 | 512 |
531 def quiet_run(self, result, func, *args, **kwargs): | 513 def quiet_run(self, result, func, *args, **kwargs): |
532 try: | 514 try: |
533 func(*args, **kwargs) | 515 func(*args, **kwargs) |
534 except (KeyboardInterrupt, SystemExit): | 516 except (KeyboardInterrupt, SystemExit): |
535 raise | 517 raise |
| 518 except unittest.SkipTest as e: |
| 519 if hasattr(result, 'addSkip'): |
| 520 result.addSkip(self, str(e)) |
| 521 else: |
| 522 warnings.warn("TestResult has no addSkip method, skips not repor
ted", |
| 523 RuntimeWarning, 2) |
| 524 result.addSuccess(self) |
| 525 return False |
536 except: | 526 except: |
537 result.addError(self, self.__exc_info()) | 527 result.addError(self, self.__exc_info()) |
538 return False | 528 return False |
539 return True | 529 return True |
540 | 530 |
541 def _get_test_method(self): | 531 def _get_test_method(self): |
542 """return the test method""" | 532 """return the test method""" |
543 return getattr(self, self._testMethodName) | 533 return getattr(self, self._testMethodName) |
544 | 534 |
545 def optval(self, option, default=None): | 535 def optval(self, option, default=None): |
546 """return the option value or default if the option is not define""" | 536 """return the option value or default if the option is not define""" |
547 return getattr(self._options_, option, default) | 537 return getattr(self._options_, option, default) |
548 | 538 |
549 def __call__(self, result=None, runcondition=None, options=None): | 539 def __call__(self, result=None, runcondition=None, options=None): |
550 """rewrite TestCase.__call__ to support generative tests | 540 """rewrite TestCase.__call__ to support generative tests |
551 This is mostly a copy/paste from unittest.py (i.e same | 541 This is mostly a copy/paste from unittest.py (i.e same |
552 variable names, same logic, except for the generative tests part) | 542 variable names, same logic, except for the generative tests part) |
553 """ | 543 """ |
554 from logilab.common.pytest import FILE_RESTART | 544 from logilab.common.pytest import FILE_RESTART |
555 if result is None: | 545 if result is None: |
556 result = self.defaultTestResult() | 546 result = self.defaultTestResult() |
557 result.pdbclass = self.pdbclass | 547 result.pdbclass = self.pdbclass |
558 self._options_ = options | 548 self._options_ = options |
559 # if result.cvg: | 549 # if result.cvg: |
560 # result.cvg.start() | 550 # result.cvg.start() |
561 testMethod = self._get_test_method() | 551 testMethod = self._get_test_method() |
| 552 if (getattr(self.__class__, "__unittest_skip__", False) or |
| 553 getattr(testMethod, "__unittest_skip__", False)): |
| 554 # If the class or method was skipped. |
| 555 try: |
| 556 skip_why = (getattr(self.__class__, '__unittest_skip_why__', '') |
| 557 or getattr(testMethod, '__unittest_skip_why__', '')) |
| 558 self._addSkip(result, skip_why) |
| 559 finally: |
| 560 result.stopTest(self) |
| 561 return |
562 if runcondition and not runcondition(testMethod): | 562 if runcondition and not runcondition(testMethod): |
563 return # test is skipped | 563 return # test is skipped |
564 result.startTest(self) | 564 result.startTest(self) |
565 try: | 565 try: |
566 if not self.quiet_run(result, self.setUp): | 566 if not self.quiet_run(result, self.setUp): |
567 return | 567 return |
568 generative = is_generator(testMethod.im_func) | 568 generative = isgeneratorfunction(testMethod) |
569 # generative tests | 569 # generative tests |
570 if generative: | 570 if generative: |
571 self._proceed_generative(result, testMethod, | 571 self._proceed_generative(result, testMethod, |
572 runcondition) | 572 runcondition) |
573 else: | 573 else: |
574 status = self._proceed(result, testMethod) | 574 status = self._proceed(result, testMethod) |
575 success = (status == 0) | 575 success = (status == 0) |
576 if not self.quiet_run(result, self.tearDown): | 576 if not self.quiet_run(result, self.tearDown): |
577 return | 577 return |
578 if not generative and success: | 578 if not generative and success: |
579 if hasattr(options, "exitfirst") and options.exitfirst: | 579 if hasattr(options, "exitfirst") and options.exitfirst: |
580 # add this test to restart file | 580 # add this test to restart file |
581 try: | 581 try: |
582 restartfile = open(FILE_RESTART, 'a') | 582 restartfile = open(FILE_RESTART, 'a') |
583 try: | 583 try: |
584 descr = '.'.join((self.__class__.__module__, | 584 descr = '.'.join((self.__class__.__module__, |
585 self.__class__.__name__, | 585 self.__class__.__name__, |
586 self._testMethodName)) | 586 self._testMethodName)) |
587 restartfile.write(descr+os.linesep) | 587 restartfile.write(descr+os.linesep) |
588 finally: | 588 finally: |
589 restartfile.close() | 589 restartfile.close() |
590 except Exception, ex: | 590 except Exception: |
591 print >> sys.__stderr__, "Error while saving \ | 591 print("Error while saving succeeded test into", |
592 succeeded test into", osp.join(os.getcwd(), FILE_RESTART) | 592 osp.join(os.getcwd(), FILE_RESTART), |
593 raise ex | 593 file=sys.__stderr__) |
| 594 raise |
594 result.addSuccess(self) | 595 result.addSuccess(self) |
595 finally: | 596 finally: |
596 # if result.cvg: | 597 # if result.cvg: |
597 # result.cvg.stop() | 598 # result.cvg.stop() |
598 result.stopTest(self) | 599 result.stopTest(self) |
599 | 600 |
600 def _proceed_generative(self, result, testfunc, runcondition=None): | 601 def _proceed_generative(self, result, testfunc, runcondition=None): |
601 # cancel startTest()'s increment | 602 # cancel startTest()'s increment |
602 result.testsRun -= 1 | 603 result.testsRun -= 1 |
603 success = True | 604 success = True |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 successful | 641 successful |
641 """ | 642 """ |
642 kwargs = kwargs or {} | 643 kwargs = kwargs or {} |
643 try: | 644 try: |
644 testfunc(*args, **kwargs) | 645 testfunc(*args, **kwargs) |
645 except self.failureException: | 646 except self.failureException: |
646 result.addFailure(self, self.__exc_info()) | 647 result.addFailure(self, self.__exc_info()) |
647 return 1 | 648 return 1 |
648 except KeyboardInterrupt: | 649 except KeyboardInterrupt: |
649 raise | 650 raise |
650 except InnerTestSkipped, e: | 651 except InnerTestSkipped as e: |
651 result.addSkip(self, e) | 652 result.addSkip(self, e) |
652 return 1 | 653 return 1 |
653 except SkipTest, e: | 654 except SkipTest as e: |
654 result.addSkip(self, e) | 655 result.addSkip(self, e) |
655 return 0 | 656 return 0 |
656 except: | 657 except: |
657 result.addError(self, self.__exc_info()) | 658 result.addError(self, self.__exc_info()) |
658 return 2 | 659 return 2 |
659 return 0 | 660 return 0 |
660 | 661 |
661 def defaultTestResult(self): | 662 def defaultTestResult(self): |
662 """return a new instance of the defaultTestResult""" | 663 """return a new instance of the defaultTestResult""" |
663 return SkipAwareTestResult() | 664 return SkipAwareTestResult() |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 msgs.append('dict2 is lacking %r' % dict1) | 698 msgs.append('dict2 is lacking %r' % dict1) |
698 if msg: | 699 if msg: |
699 self.failureException(msg) | 700 self.failureException(msg) |
700 elif msgs: | 701 elif msgs: |
701 if context is not None: | 702 if context is not None: |
702 base = '%s\n' % context | 703 base = '%s\n' % context |
703 else: | 704 else: |
704 base = '' | 705 base = '' |
705 self.fail(base + '\n'.join(msgs)) | 706 self.fail(base + '\n'.join(msgs)) |
706 | 707 |
707 @deprecated('Please use assertItemsEqual instead.') | 708 @deprecated('Please use assertCountEqual instead.') |
708 def assertUnorderedIterableEquals(self, got, expected, msg=None): | 709 def assertUnorderedIterableEquals(self, got, expected, msg=None): |
709 """compares two iterable and shows difference between both | 710 """compares two iterable and shows difference between both |
710 | 711 |
711 :param got: the unordered Iterable that we found | 712 :param got: the unordered Iterable that we found |
712 :param expected: the expected unordered Iterable | 713 :param expected: the expected unordered Iterable |
713 :param msg: custom message (String) in case of failure | 714 :param msg: custom message (String) in case of failure |
714 """ | 715 """ |
715 got, expected = list(got), list(expected) | 716 got, expected = list(got), list(expected) |
716 self.assertSetEqual(set(got), set(expected), msg) | 717 self.assertSetEqual(set(got), set(expected), msg) |
717 if len(got) != len(expected): | 718 if len(got) != len(expected): |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 Only available with element tree | 820 Only available with element tree |
820 """ | 821 """ |
821 try: | 822 try: |
822 from xml.etree.ElementTree import parse | 823 from xml.etree.ElementTree import parse |
823 self._assertETXMLWellFormed(stream, parse, msg) | 824 self._assertETXMLWellFormed(stream, parse, msg) |
824 except ImportError: | 825 except ImportError: |
825 from xml.sax import make_parser, SAXParseException | 826 from xml.sax import make_parser, SAXParseException |
826 parser = make_parser() | 827 parser = make_parser() |
827 try: | 828 try: |
828 parser.parse(stream) | 829 parser.parse(stream) |
829 except SAXParseException, ex: | 830 except SAXParseException as ex: |
830 if msg is None: | 831 if msg is None: |
831 stream.seek(0) | 832 stream.seek(0) |
832 for _ in xrange(ex.getLineNumber()): | 833 for _ in range(ex.getLineNumber()): |
833 line = stream.readline() | 834 line = stream.readline() |
834 pointer = ('' * (ex.getLineNumber() - 1)) + '^' | 835 pointer = ('' * (ex.getLineNumber() - 1)) + '^' |
835 msg = 'XML stream not well formed: %s\n%s%s' % (ex, line, po
inter) | 836 msg = 'XML stream not well formed: %s\n%s%s' % (ex, line, po
inter) |
836 self.fail(msg) | 837 self.fail(msg) |
837 | 838 |
838 @deprecated('Non-standard: please copy test method to your TestCase class') | 839 @deprecated('Non-standard: please copy test method to your TestCase class') |
839 def assertXMLStringWellFormed(self, xml_string, msg=None, context=2): | 840 def assertXMLStringWellFormed(self, xml_string, msg=None, context=2): |
840 """asserts the XML string is well-formed (no DTD conformance check) | 841 """asserts the XML string is well-formed (no DTD conformance check) |
841 | 842 |
842 :param context: number of context lines in standard message | 843 :param context: number of context lines in standard message |
(...skipping 17 matching lines...) Expand all Loading... |
860 Only available with element tree | 861 Only available with element tree |
861 """ | 862 """ |
862 from xml.parsers.expat import ExpatError | 863 from xml.parsers.expat import ExpatError |
863 try: | 864 try: |
864 from xml.etree.ElementTree import ParseError | 865 from xml.etree.ElementTree import ParseError |
865 except ImportError: | 866 except ImportError: |
866 # compatibility for <python2.7 | 867 # compatibility for <python2.7 |
867 ParseError = ExpatError | 868 ParseError = ExpatError |
868 try: | 869 try: |
869 parse(data) | 870 parse(data) |
870 except (ExpatError, ParseError), ex: | 871 except (ExpatError, ParseError) as ex: |
871 if msg is None: | 872 if msg is None: |
872 if hasattr(data, 'readlines'): #file like object | 873 if hasattr(data, 'readlines'): #file like object |
873 data.seek(0) | 874 data.seek(0) |
874 lines = data.readlines() | 875 lines = data.readlines() |
875 else: | 876 else: |
876 lines = data.splitlines(True) | 877 lines = data.splitlines(True) |
877 nb_lines = len(lines) | 878 nb_lines = len(lines) |
878 context_lines = [] | 879 context_lines = [] |
879 | 880 |
880 # catch when ParseError doesn't set valid lineno | 881 # catch when ParseError doesn't set valid lineno |
881 if ex.lineno is not None: | 882 if ex.lineno is not None: |
882 if context < 0: | 883 if context < 0: |
883 start = 1 | 884 start = 1 |
884 end = nb_lines | 885 end = nb_lines |
885 else: | 886 else: |
886 start = max(ex.lineno-context, 1) | 887 start = max(ex.lineno-context, 1) |
887 end = min(ex.lineno+context, nb_lines) | 888 end = min(ex.lineno+context, nb_lines) |
888 line_number_length = len('%i' % end) | 889 line_number_length = len('%i' % end) |
889 line_pattern = " %%%ii: %%s" % line_number_length | 890 line_pattern = " %%%ii: %%s" % line_number_length |
890 | 891 |
891 for line_no in xrange(start, ex.lineno): | 892 for line_no in range(start, ex.lineno): |
892 context_lines.append(line_pattern % (line_no, lines[line
_no-1])) | 893 context_lines.append(line_pattern % (line_no, lines[line
_no-1])) |
893 context_lines.append(line_pattern % (ex.lineno, lines[ex.lin
eno-1])) | 894 context_lines.append(line_pattern % (ex.lineno, lines[ex.lin
eno-1])) |
894 context_lines.append('%s^\n' % (' ' * (1 + line_number_lengt
h + 2 +ex.offset))) | 895 context_lines.append('%s^\n' % (' ' * (1 + line_number_lengt
h + 2 +ex.offset))) |
895 for line_no in xrange(ex.lineno+1, end+1): | 896 for line_no in range(ex.lineno+1, end+1): |
896 context_lines.append(line_pattern % (line_no, lines[line
_no-1])) | 897 context_lines.append(line_pattern % (line_no, lines[line
_no-1])) |
897 | 898 |
898 rich_context = ''.join(context_lines) | 899 rich_context = ''.join(context_lines) |
899 msg = 'XML stream not well formed: %s\n%s' % (ex, rich_context) | 900 msg = 'XML stream not well formed: %s\n%s' % (ex, rich_context) |
900 self.fail(msg) | 901 self.fail(msg) |
901 | 902 |
902 @deprecated('Non-standard: please copy test method to your TestCase class') | 903 @deprecated('Non-standard: please copy test method to your TestCase class') |
903 def assertXMLEqualsTuple(self, element, tup): | 904 def assertXMLEqualsTuple(self, element, tup): |
904 """compare an ElementTree Element to a tuple formatted as follow: | 905 """compare an ElementTree Element to a tuple formatted as follow: |
905 (tagname, [attrib[, children[, text[, tail]]]])""" | 906 (tagname, [attrib[, children[, text[, tail]]]])""" |
906 # check tag | 907 # check tag |
907 self.assertTextEquals(element.tag, tup[0]) | 908 self.assertTextEquals(element.tag, tup[0]) |
908 # check attrib | 909 # check attrib |
909 if len(element.attrib) or len(tup)>1: | 910 if len(element.attrib) or len(tup)>1: |
910 if len(tup)<=1: | 911 if len(tup)<=1: |
911 self.fail( "tuple %s has no attributes (%s expected)"%(tup, | 912 self.fail( "tuple %s has no attributes (%s expected)"%(tup, |
912 dict(element.attrib))) | 913 dict(element.attrib))) |
913 self.assertDictEqual(element.attrib, tup[1]) | 914 self.assertDictEqual(element.attrib, tup[1]) |
914 # check children | 915 # check children |
915 if len(element) or len(tup)>2: | 916 if len(element) or len(tup)>2: |
916 if len(tup)<=2: | 917 if len(tup)<=2: |
917 self.fail( "tuple %s has no children (%i expected)"%(tup, | 918 self.fail( "tuple %s has no children (%i expected)"%(tup, |
918 len(element))) | 919 len(element))) |
919 if len(element) != len(tup[2]): | 920 if len(element) != len(tup[2]): |
920 self.fail( "tuple %s has %i children%s (%i expected)"%(tup, | 921 self.fail( "tuple %s has %i children%s (%i expected)"%(tup, |
921 len(tup[2]), | 922 len(tup[2]), |
922 ('', 's')[len(tup[2])>1], len(element))) | 923 ('', 's')[len(tup[2])>1], len(element))) |
923 for index in xrange(len(tup[2])): | 924 for index in range(len(tup[2])): |
924 self.assertXMLEqualsTuple(element[index], tup[2][index]) | 925 self.assertXMLEqualsTuple(element[index], tup[2][index]) |
925 #check text | 926 #check text |
926 if element.text or len(tup)>3: | 927 if element.text or len(tup)>3: |
927 if len(tup)<=3: | 928 if len(tup)<=3: |
928 self.fail( "tuple %s has no text value (%r expected)"%(tup, | 929 self.fail( "tuple %s has no text value (%r expected)"%(tup, |
929 element.text)) | 930 element.text)) |
930 self.assertTextEquals(element.text, tup[3]) | 931 self.assertTextEquals(element.text, tup[3]) |
931 #check tail | 932 #check tail |
932 if element.tail or len(tup)>4: | 933 if element.tail or len(tup)>4: |
933 if len(tup)<=4: | 934 if len(tup)<=4: |
934 self.fail( "tuple %s has no tail value (%r expected)"%(tup, | 935 self.fail( "tuple %s has no tail value (%r expected)"%(tup, |
935 element.tail)) | 936 element.tail)) |
936 self.assertTextEquals(element.tail, tup[4]) | 937 self.assertTextEquals(element.tail, tup[4]) |
937 | 938 |
938 def _difftext(self, lines1, lines2, junk=None, msg_prefix='Texts differ'): | 939 def _difftext(self, lines1, lines2, junk=None, msg_prefix='Texts differ'): |
939 junk = junk or (' ', '\t') | 940 junk = junk or (' ', '\t') |
940 # result is a generator | 941 # result is a generator |
941 result = difflib.ndiff(lines1, lines2, charjunk=lambda x: x in junk) | 942 result = difflib.ndiff(lines1, lines2, charjunk=lambda x: x in junk) |
942 read = [] | 943 read = [] |
943 for line in result: | 944 for line in result: |
944 read.append(line) | 945 read.append(line) |
945 # lines that don't start with a ' ' are diff ones | 946 # lines that don't start with a ' ' are diff ones |
946 if not line.startswith(' '): | 947 if not line.startswith(' '): |
947 self.fail('\n'.join(['%s\n'%msg_prefix]+read + list(result))) | 948 self.fail('\n'.join(['%s\n'%msg_prefix]+read + list(result))) |
948 | 949 |
949 @deprecated('Non-standard. Please use assertMultiLineEqual instead.') | 950 @deprecated('Non-standard. Please use assertMultiLineEqual instead.') |
950 def assertTextEquals(self, text1, text2, junk=None, | 951 def assertTextEquals(self, text1, text2, junk=None, |
951 msg_prefix='Text differ', striplines=False): | 952 msg_prefix='Text differ', striplines=False): |
952 """compare two multiline strings (using difflib and splitlines()) | 953 """compare two multiline strings (using difflib and splitlines()) |
953 | 954 |
954 :param text1: a Python BaseString | 955 :param text1: a Python BaseString |
955 :param text2: a second Python Basestring | 956 :param text2: a second Python Basestring |
956 :param junk: List of Caracters | 957 :param junk: List of Caracters |
957 :param msg_prefix: String (message prefix) | 958 :param msg_prefix: String (message prefix) |
958 :param striplines: Boolean to trigger line stripping before comparing | 959 :param striplines: Boolean to trigger line stripping before comparing |
959 """ | 960 """ |
960 msg = [] | 961 msg = [] |
961 if not isinstance(text1, basestring): | 962 if not isinstance(text1, string_types): |
962 msg.append('text1 is not a string (%s)'%(type(text1))) | 963 msg.append('text1 is not a string (%s)'%(type(text1))) |
963 if not isinstance(text2, basestring): | 964 if not isinstance(text2, string_types): |
964 msg.append('text2 is not a string (%s)'%(type(text2))) | 965 msg.append('text2 is not a string (%s)'%(type(text2))) |
965 if msg: | 966 if msg: |
966 self.fail('\n'.join(msg)) | 967 self.fail('\n'.join(msg)) |
967 lines1 = text1.strip().splitlines(True) | 968 lines1 = text1.strip().splitlines(True) |
968 lines2 = text2.strip().splitlines(True) | 969 lines2 = text2.strip().splitlines(True) |
969 if striplines: | 970 if striplines: |
970 lines1 = [line.strip() for line in lines1] | 971 lines1 = [line.strip() for line in lines1] |
971 lines2 = [line.strip() for line in lines2] | 972 lines2 = [line.strip() for line in lines2] |
972 self._difftext(lines1, lines2, junk, msg_prefix) | 973 self._difftext(lines1, lines2, junk, msg_prefix) |
973 assertTextEqual = assertTextEquals | 974 assertTextEqual = assertTextEquals |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 | 1010 |
1010 all_b = [ (ipath[len(path_b):].lstrip('/'), idirs, ifiles) | 1011 all_b = [ (ipath[len(path_b):].lstrip('/'), idirs, ifiles) |
1011 for ipath, idirs, ifiles in os.walk(path_b)] | 1012 for ipath, idirs, ifiles in os.walk(path_b)] |
1012 all_b.sort(key=itemgetter(0)) | 1013 all_b.sort(key=itemgetter(0)) |
1013 | 1014 |
1014 iter_a, iter_b = iter(all_a), iter(all_b) | 1015 iter_a, iter_b = iter(all_a), iter(all_b) |
1015 partial_iter = True | 1016 partial_iter = True |
1016 ipath_a, idirs_a, ifiles_a = data_a = None, None, None | 1017 ipath_a, idirs_a, ifiles_a = data_a = None, None, None |
1017 while True: | 1018 while True: |
1018 try: | 1019 try: |
1019 ipath_a, idirs_a, ifiles_a = datas_a = iter_a.next() | 1020 ipath_a, idirs_a, ifiles_a = datas_a = next(iter_a) |
1020 partial_iter = False | 1021 partial_iter = False |
1021 ipath_b, idirs_b, ifiles_b = datas_b = iter_b.next() | 1022 ipath_b, idirs_b, ifiles_b = datas_b = next(iter_b) |
1022 partial_iter = True | 1023 partial_iter = True |
1023 | 1024 |
1024 | 1025 |
1025 self.assert_(ipath_a == ipath_b, | 1026 self.assertTrue(ipath_a == ipath_b, |
1026 "unexpected %s in %s while looking %s from %s" % | 1027 "unexpected %s in %s while looking %s from %s" % |
1027 (ipath_a, path_a, ipath_b, path_b)) | 1028 (ipath_a, path_a, ipath_b, path_b)) |
1028 | 1029 |
1029 | 1030 |
1030 errors = {} | 1031 errors = {} |
1031 sdirs_a = set(idirs_a) | 1032 sdirs_a = set(idirs_a) |
1032 sdirs_b = set(idirs_b) | 1033 sdirs_b = set(idirs_b) |
1033 errors["unexpected directories"] = sdirs_a - sdirs_b | 1034 errors["unexpected directories"] = sdirs_a - sdirs_b |
1034 errors["missing directories"] = sdirs_b - sdirs_a | 1035 errors["missing directories"] = sdirs_b - sdirs_a |
1035 | 1036 |
1036 sfiles_a = set(ifiles_a) | 1037 sfiles_a = set(ifiles_a) |
1037 sfiles_b = set(ifiles_b) | 1038 sfiles_b = set(ifiles_b) |
1038 errors["unexpected files"] = sfiles_a - sfiles_b | 1039 errors["unexpected files"] = sfiles_a - sfiles_b |
1039 errors["missing files"] = sfiles_b - sfiles_a | 1040 errors["missing files"] = sfiles_b - sfiles_a |
1040 | 1041 |
1041 | 1042 |
1042 msgs = [ "%s: %s"% (name, items) | 1043 msgs = [ "%s: %s"% (name, items) |
1043 for name, items in errors.iteritems() if items] | 1044 for name, items in errors.items() if items] |
1044 | 1045 |
1045 if msgs: | 1046 if msgs: |
1046 msgs.insert(0, "%s and %s differ :" % ( | 1047 msgs.insert(0, "%s and %s differ :" % ( |
1047 osp.join(path_a, ipath_a), | 1048 osp.join(path_a, ipath_a), |
1048 osp.join(path_b, ipath_b), | 1049 osp.join(path_b, ipath_b), |
1049 )) | 1050 )) |
1050 self.fail("\n".join(msgs)) | 1051 self.fail("\n".join(msgs)) |
1051 | 1052 |
1052 for files in (ifiles_a, ifiles_b): | 1053 for files in (ifiles_a, ifiles_b): |
1053 files.sort() | 1054 files.sort() |
(...skipping 19 matching lines...) Expand all Loading... |
1073 if strict: | 1074 if strict: |
1074 warnings.warn('[API] Non-standard. Strict parameter has vanished', | 1075 warnings.warn('[API] Non-standard. Strict parameter has vanished', |
1075 DeprecationWarning, stacklevel=2) | 1076 DeprecationWarning, stacklevel=2) |
1076 if msg is None: | 1077 if msg is None: |
1077 if strict: | 1078 if strict: |
1078 msg = '%r is not of class %s but of %s' | 1079 msg = '%r is not of class %s but of %s' |
1079 else: | 1080 else: |
1080 msg = '%r is not an instance of %s but of %s' | 1081 msg = '%r is not an instance of %s but of %s' |
1081 msg = msg % (obj, klass, type(obj)) | 1082 msg = msg % (obj, klass, type(obj)) |
1082 if strict: | 1083 if strict: |
1083 self.assert_(obj.__class__ is klass, msg) | 1084 self.assertTrue(obj.__class__ is klass, msg) |
1084 else: | 1085 else: |
1085 self.assert_(isinstance(obj, klass), msg) | 1086 self.assertTrue(isinstance(obj, klass), msg) |
1086 | 1087 |
1087 @deprecated('Please use assertIsNone instead.') | 1088 @deprecated('Please use assertIsNone instead.') |
1088 def assertNone(self, obj, msg=None): | 1089 def assertNone(self, obj, msg=None): |
1089 """assert obj is None | 1090 """assert obj is None |
1090 | 1091 |
1091 :param obj: Python Object to be tested | 1092 :param obj: Python Object to be tested |
1092 """ | 1093 """ |
1093 if msg is None: | 1094 if msg is None: |
1094 msg = "reference to %r when None expected"%(obj,) | 1095 msg = "reference to %r when None expected"%(obj,) |
1095 self.assert_( obj is None, msg ) | 1096 self.assertTrue( obj is None, msg ) |
1096 | 1097 |
1097 @deprecated('Please use assertIsNotNone instead.') | 1098 @deprecated('Please use assertIsNotNone instead.') |
1098 def assertNotNone(self, obj, msg=None): | 1099 def assertNotNone(self, obj, msg=None): |
1099 """assert obj is not None""" | 1100 """assert obj is not None""" |
1100 if msg is None: | 1101 if msg is None: |
1101 msg = "unexpected reference to None" | 1102 msg = "unexpected reference to None" |
1102 self.assert_( obj is not None, msg ) | 1103 self.assertTrue( obj is not None, msg ) |
1103 | 1104 |
1104 @deprecated('Non-standard. Please use assertAlmostEqual instead.') | 1105 @deprecated('Non-standard. Please use assertAlmostEqual instead.') |
1105 def assertFloatAlmostEquals(self, obj, other, prec=1e-5, | 1106 def assertFloatAlmostEquals(self, obj, other, prec=1e-5, |
1106 relative=False, msg=None): | 1107 relative=False, msg=None): |
1107 """compares if two floats have a distance smaller than expected | 1108 """compares if two floats have a distance smaller than expected |
1108 precision. | 1109 precision. |
1109 | 1110 |
1110 :param obj: a Float | 1111 :param obj: a Float |
1111 :param other: another Float to be comparted to <obj> | 1112 :param other: another Float to be comparted to <obj> |
1112 :param prec: a Float describing the precision | 1113 :param prec: a Float describing the precision |
1113 :param relative: boolean switching to relative/absolute precision | 1114 :param relative: boolean switching to relative/absolute precision |
1114 :param msg: a String for a custom message | 1115 :param msg: a String for a custom message |
1115 """ | 1116 """ |
1116 if msg is None: | 1117 if msg is None: |
1117 msg = "%r != %r" % (obj, other) | 1118 msg = "%r != %r" % (obj, other) |
1118 if relative: | 1119 if relative: |
1119 prec = prec*math.fabs(obj) | 1120 prec = prec*math.fabs(obj) |
1120 self.assert_(math.fabs(obj - other) < prec, msg) | 1121 self.assertTrue(math.fabs(obj - other) < prec, msg) |
1121 | 1122 |
1122 def failUnlessRaises(self, excClass, callableObj=None, *args, **kwargs): | 1123 def failUnlessRaises(self, excClass, callableObj=None, *args, **kwargs): |
1123 """override default failUnlessRaises method to return the raised | 1124 """override default failUnlessRaises method to return the raised |
1124 exception instance. | 1125 exception instance. |
1125 | 1126 |
1126 Fail unless an exception of class excClass is thrown | 1127 Fail unless an exception of class excClass is thrown |
1127 by callableObj when invoked with arguments args and keyword | 1128 by callableObj when invoked with arguments args and keyword |
1128 arguments kwargs. If a different type of exception is | 1129 arguments kwargs. If a different type of exception is |
1129 thrown, it will not be caught, and the test case will be | 1130 thrown, it will not be caught, and the test case will be |
1130 deemed to have suffered an error, exactly as for an | 1131 deemed to have suffered an error, exactly as for an |
1131 unexpected exception. | 1132 unexpected exception. |
1132 | 1133 |
1133 CAUTION! There are subtle differences between Logilab and unittest2 | 1134 CAUTION! There are subtle differences between Logilab and unittest2 |
1134 - exc is not returned in standard version | 1135 - exc is not returned in standard version |
1135 - context capabilities in standard version | 1136 - context capabilities in standard version |
1136 - try/except/else construction (minor) | 1137 - try/except/else construction (minor) |
1137 | 1138 |
1138 :param excClass: the Exception to be raised | 1139 :param excClass: the Exception to be raised |
1139 :param callableObj: a callable Object which should raise <excClass> | 1140 :param callableObj: a callable Object which should raise <excClass> |
1140 :param args: a List of arguments for <callableObj> | 1141 :param args: a List of arguments for <callableObj> |
1141 :param kwargs: a List of keyword arguments for <callableObj> | 1142 :param kwargs: a List of keyword arguments for <callableObj> |
1142 """ | 1143 """ |
1143 # XXX cube vcslib : test_branches_from_app | 1144 # XXX cube vcslib : test_branches_from_app |
1144 if callableObj is None: | 1145 if callableObj is None: |
1145 _assert = super(TestCase, self).assertRaises | 1146 _assert = super(TestCase, self).assertRaises |
1146 return _assert(excClass, callableObj, *args, **kwargs) | 1147 return _assert(excClass, callableObj, *args, **kwargs) |
1147 try: | 1148 try: |
1148 callableObj(*args, **kwargs) | 1149 callableObj(*args, **kwargs) |
1149 except excClass, exc: | 1150 except excClass as exc: |
1150 class ProxyException: | 1151 class ProxyException: |
1151 def __init__(self, obj): | 1152 def __init__(self, obj): |
1152 self._obj = obj | 1153 self._obj = obj |
1153 def __getattr__(self, attr): | 1154 def __getattr__(self, attr): |
1154 warn_msg = ("This exception was retrieved with the old testl
ib way " | 1155 warn_msg = ("This exception was retrieved with the old testl
ib way " |
1155 "`exc = self.assertRaises(Exc, callable)`, pleas
e use " | 1156 "`exc = self.assertRaises(Exc, callable)`, pleas
e use " |
1156 "the context manager instead'") | 1157 "the context manager instead'") |
1157 warnings.warn(warn_msg, DeprecationWarning, 2) | 1158 warnings.warn(warn_msg, DeprecationWarning, 2) |
1158 return self._obj.__getattribute__(attr) | 1159 return self._obj.__getattribute__(attr) |
1159 return ProxyException(exc) | 1160 return ProxyException(exc) |
1160 else: | 1161 else: |
1161 if hasattr(excClass, '__name__'): | 1162 if hasattr(excClass, '__name__'): |
1162 excName = excClass.__name__ | 1163 excName = excClass.__name__ |
1163 else: | 1164 else: |
1164 excName = str(excClass) | 1165 excName = str(excClass) |
1165 raise self.failureException("%s not raised" % excName) | 1166 raise self.failureException("%s not raised" % excName) |
1166 | 1167 |
1167 assertRaises = failUnlessRaises | 1168 assertRaises = failUnlessRaises |
1168 | 1169 |
| 1170 if sys.version_info >= (3,2): |
| 1171 assertItemsEqual = unittest.TestCase.assertCountEqual |
| 1172 else: |
| 1173 assertCountEqual = unittest.TestCase.assertItemsEqual |
| 1174 if sys.version_info < (2,7): |
| 1175 def assertIsNotNone(self, value, *args, **kwargs): |
| 1176 self.assertNotEqual(None, value, *args, **kwargs) |
| 1177 |
| 1178 TestCase.assertItemsEqual = deprecated('assertItemsEqual is deprecated, use asse
rtCountEqual')( |
| 1179 TestCase.assertItemsEqual) |
1169 | 1180 |
1170 import doctest | 1181 import doctest |
1171 | 1182 |
1172 class SkippedSuite(unittest.TestSuite): | 1183 class SkippedSuite(unittest.TestSuite): |
1173 def test(self): | 1184 def test(self): |
1174 """just there to trigger test execution""" | 1185 """just there to trigger test execution""" |
1175 self.skipped_test('doctest module has no DocTestSuite class') | 1186 self.skipped_test('doctest module has no DocTestSuite class') |
1176 | 1187 |
1177 | 1188 |
1178 class DocTestFinder(doctest.DocTestFinder): | 1189 class DocTestFinder(doctest.DocTestFinder): |
1179 | 1190 |
1180 def __init__(self, *args, **kwargs): | 1191 def __init__(self, *args, **kwargs): |
1181 self.skipped = kwargs.pop('skipped', ()) | 1192 self.skipped = kwargs.pop('skipped', ()) |
1182 doctest.DocTestFinder.__init__(self, *args, **kwargs) | 1193 doctest.DocTestFinder.__init__(self, *args, **kwargs) |
1183 | 1194 |
1184 def _get_test(self, obj, name, module, globs, source_lines): | 1195 def _get_test(self, obj, name, module, globs, source_lines): |
1185 """override default _get_test method to be able to skip tests | 1196 """override default _get_test method to be able to skip tests |
1186 according to skipped attribute's value | 1197 according to skipped attribute's value |
1187 | |
1188 Note: Python (<=2.4) use a _name_filter which could be used for that | |
1189 purpose but it's no longer available in 2.5 | |
1190 Python 2.5 seems to have a [SKIP] flag | |
1191 """ | 1198 """ |
1192 if getattr(obj, '__name__', '') in self.skipped: | 1199 if getattr(obj, '__name__', '') in self.skipped: |
1193 return None | 1200 return None |
1194 return doctest.DocTestFinder._get_test(self, obj, name, module, | 1201 return doctest.DocTestFinder._get_test(self, obj, name, module, |
1195 globs, source_lines) | 1202 globs, source_lines) |
1196 | 1203 |
1197 | 1204 |
1198 class DocTest(TestCase): | 1205 class DocTest(TestCase): |
1199 """trigger module doctest | 1206 """trigger module doctest |
1200 I don't know how to make unittest.main consider the DocTestSuite instance | 1207 I don't know how to make unittest.main consider the DocTestSuite instance |
1201 without this hack | 1208 without this hack |
1202 """ | 1209 """ |
1203 skipped = () | 1210 skipped = () |
1204 def __call__(self, result=None, runcondition=None, options=None):\ | 1211 def __call__(self, result=None, runcondition=None, options=None):\ |
1205 # pylint: disable=W0613 | 1212 # pylint: disable=W0613 |
1206 try: | 1213 try: |
1207 finder = DocTestFinder(skipped=self.skipped) | 1214 finder = DocTestFinder(skipped=self.skipped) |
1208 if sys.version_info >= (2, 4): | 1215 suite = doctest.DocTestSuite(self.module, test_finder=finder) |
1209 suite = doctest.DocTestSuite(self.module, test_finder=finder) | 1216 # XXX iirk |
1210 if sys.version_info >= (2, 5): | 1217 doctest.DocTestCase._TestCase__exc_info = sys.exc_info |
1211 # XXX iirk | |
1212 doctest.DocTestCase._TestCase__exc_info = sys.exc_info | |
1213 else: | |
1214 suite = doctest.DocTestSuite(self.module) | |
1215 except AttributeError: | 1218 except AttributeError: |
1216 suite = SkippedSuite() | 1219 suite = SkippedSuite() |
1217 return suite.run(result) | 1220 # doctest may gork the builtins dictionnary |
| 1221 # This happen to the "_" entry used by gettext |
| 1222 old_builtins = builtins.__dict__.copy() |
| 1223 try: |
| 1224 return suite.run(result) |
| 1225 finally: |
| 1226 builtins.__dict__.clear() |
| 1227 builtins.__dict__.update(old_builtins) |
1218 run = __call__ | 1228 run = __call__ |
1219 | 1229 |
1220 def test(self): | 1230 def test(self): |
1221 """just there to trigger test execution""" | 1231 """just there to trigger test execution""" |
1222 | 1232 |
1223 MAILBOX = None | 1233 MAILBOX = None |
1224 | 1234 |
1225 class MockSMTP: | 1235 class MockSMTP: |
1226 """fake smtplib.SMTP""" | 1236 """fake smtplib.SMTP""" |
1227 | 1237 |
1228 def __init__(self, host, port): | 1238 def __init__(self, host, port): |
1229 self.host = host | 1239 self.host = host |
1230 self.port = port | 1240 self.port = port |
1231 global MAILBOX | 1241 global MAILBOX |
1232 self.reveived = MAILBOX = [] | 1242 self.reveived = MAILBOX = [] |
1233 | 1243 |
1234 def set_debuglevel(self, debuglevel): | 1244 def set_debuglevel(self, debuglevel): |
1235 """ignore debug level""" | 1245 """ignore debug level""" |
1236 | 1246 |
1237 def sendmail(self, fromaddr, toaddres, body): | 1247 def sendmail(self, fromaddr, toaddres, body): |
1238 """push sent mail in the mailbox""" | 1248 """push sent mail in the mailbox""" |
1239 self.reveived.append((fromaddr, toaddres, body)) | 1249 self.reveived.append((fromaddr, toaddres, body)) |
1240 | 1250 |
1241 def quit(self): | 1251 def quit(self): |
1242 """ignore quit""" | 1252 """ignore quit""" |
1243 | 1253 |
1244 | 1254 |
1245 class MockConfigParser(ConfigParser): | 1255 class MockConfigParser(configparser.ConfigParser): |
1246 """fake ConfigParser.ConfigParser""" | 1256 """fake ConfigParser.ConfigParser""" |
1247 | 1257 |
1248 def __init__(self, options): | 1258 def __init__(self, options): |
1249 ConfigParser.__init__(self) | 1259 configparser.ConfigParser.__init__(self) |
1250 for section, pairs in options.iteritems(): | 1260 for section, pairs in options.iteritems(): |
1251 self.add_section(section) | 1261 self.add_section(section) |
1252 for key, value in pairs.iteritems(): | 1262 for key, value in pairs.iteritems(): |
1253 self.set(section, key, value) | 1263 self.set(section, key, value) |
1254 def write(self, _): | 1264 def write(self, _): |
1255 raise NotImplementedError() | 1265 raise NotImplementedError() |
1256 | 1266 |
1257 | 1267 |
1258 class MockConnection: | 1268 class MockConnection: |
1259 """fake DB-API 2.0 connexion AND cursor (i.e. cursor() return self)""" | 1269 """fake DB-API 2.0 connexion AND cursor (i.e. cursor() return self)""" |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1373 try: | 1383 try: |
1374 __import__(module) | 1384 __import__(module) |
1375 return f | 1385 return f |
1376 except ImportError: | 1386 except ImportError: |
1377 def new_f(self, *args, **kwargs): | 1387 def new_f(self, *args, **kwargs): |
1378 self.skipTest('%s can not be imported.' % module) | 1388 self.skipTest('%s can not be imported.' % module) |
1379 new_f.__name__ = f.__name__ | 1389 new_f.__name__ = f.__name__ |
1380 return new_f | 1390 return new_f |
1381 return check_require_module | 1391 return check_require_module |
1382 | 1392 |
OLD | NEW |