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