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 |