| 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 |