Ticket #12991: unittest2-addition.diff

File unittest2-addition.diff, 124.8 KB (added by Paul McMillan, 14 years ago)

patch to bundle unittest2, fix failing tests, and use system version if possible. Updated to work against trunk.

  • django/test/simple.py

     
    11import sys
    22import signal
    3 import unittest
    43
    54from django.conf import settings
    65from django.db.models import get_app, get_apps
    76from django.test import _doctest as doctest
    87from django.test.utils import setup_test_environment, teardown_test_environment
    98from django.test.testcases import OutputChecker, DocTestRunner, TestCase
     9from django.utils import unittest
    1010
    1111# The module name for tests outside models.py
    1212TEST_MODULE = 'tests'
  • django/test/testcases.py

     
    11import re
    2 import unittest
    32from urlparse import urlsplit, urlunsplit
    43from xml.dom.minidom import parseString, Node
    54
     
    1110from django.http import QueryDict
    1211from django.test import _doctest as doctest
    1312from django.test.client import Client
    14 from django.utils import simplejson
     13from django.utils import simplejson, unittest
    1514from django.utils.encoding import smart_str
    1615
    1716try:
  • django/test/__init__.py

     
    44
    55from django.test.client import Client
    66from django.test.testcases import TestCase, TransactionTestCase
     7from django.test.utils import skipIfDBEngine
  • django/test/utils.py

     
    22from django.conf import settings
    33from django.core import mail
    44from django.core.mail.backends import locmem
     5from django.db import DEFAULT_DB_ALIAS
    56from django.test import signals
    67from django.template import Template
    78from django.utils.translation import deactivate
     9from django.utils.unittest import skipIf
    810
    911class ContextList(list):
    1012    """A wrapper that provides direct key access to context items contained
     
    7779    test_module = __import__(test_module_name, {}, {}, test_path[-1])
    7880    test_runner = getattr(test_module, test_path[-1])
    7981    return test_runner
     82
     83def skipIfDBEngine(engine, reason=None):
     84    """
     85    Decorator to skip tests on a given database engine.
     86
     87    Note that you can pass a single engine or an iterable here
     88    """
     89    if not reason:
     90        reason = "not supported on this database"
     91    settings_engine = settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE']
     92    if isinstance(engine, basestring):
     93        return skipIf(settings_engine == engine, reason)
     94    return skipIf(settings_engine in engine, reason)
  • django/utils/unittest/compatibility.py

     
     1import os
     2import sys
     3
     4try:
     5    from functools import wraps
     6except ImportError:
     7    # only needed for Python 2.4
     8    def wraps(_):
     9        def _wraps(func):
     10            return func
     11        return _wraps
     12
     13__unittest = True
     14
     15def _relpath_nt(path, start=os.path.curdir):
     16    """Return a relative version of a path"""
     17
     18    if not path:
     19        raise ValueError("no path specified")
     20    start_list = os.path.abspath(start).split(os.path.sep)
     21    path_list = os.path.abspath(path).split(os.path.sep)
     22    if start_list[0].lower() != path_list[0].lower():
     23        unc_path, rest = os.path.splitunc(path)
     24        unc_start, rest = os.path.splitunc(start)
     25        if bool(unc_path) ^ bool(unc_start):
     26            raise ValueError("Cannot mix UNC and non-UNC paths (%s and %s)"
     27                                                                % (path, start))
     28        else:
     29            raise ValueError("path is on drive %s, start on drive %s"
     30                                                % (path_list[0], start_list[0]))
     31    # Work out how much of the filepath is shared by start and path.
     32    for i in range(min(len(start_list), len(path_list))):
     33        if start_list[i].lower() != path_list[i].lower():
     34            break
     35    else:
     36        i += 1
     37
     38    rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
     39    if not rel_list:
     40        return os.path.curdir
     41    return os.path.join(*rel_list)
     42
     43# default to posixpath definition
     44def _relpath_posix(path, start=os.path.curdir):
     45    """Return a relative version of a path"""
     46
     47    if not path:
     48        raise ValueError("no path specified")
     49   
     50    start_list = os.path.abspath(start).split(os.path.sep)
     51    path_list = os.path.abspath(path).split(os.path.sep)
     52
     53    # Work out how much of the filepath is shared by start and path.
     54    i = len(os.path.commonprefix([start_list, path_list]))
     55
     56    rel_list = [os.path.pardir] * (len(start_list)-i) + path_list[i:]
     57    if not rel_list:
     58        return os.path.curdir
     59    return os.path.join(*rel_list)
     60
     61if os.path is sys.modules.get('ntpath'):
     62    relpath = _relpath_nt
     63else:
     64    relpath = _relpath_posix
  • django/utils/unittest/runner.py

     
     1"""Running tests"""
     2
     3import sys
     4import time
     5import unittest
     6
     7from django.utils.unittest import result
     8
     9try:
     10    from django.utils.unittest.signals import registerResult
     11except ImportError:
     12    def registerResult(_):
     13        pass
     14   
     15__unittest = True
     16
     17
     18class _WritelnDecorator(object):
     19    """Used to decorate file-like objects with a handy 'writeln' method"""
     20    def __init__(self,stream):
     21        self.stream = stream
     22
     23    def __getattr__(self, attr):
     24        if attr in ('stream', '__getstate__'):
     25            raise AttributeError(attr)
     26        return getattr(self.stream,attr)
     27
     28    def writeln(self, arg=None):
     29        if arg:
     30            self.write(arg)
     31        self.write('\n') # text-mode streams translate to \r\n if needed
     32
     33
     34class TextTestResult(result.TestResult):
     35    """A test result class that can print formatted text results to a stream.
     36
     37    Used by TextTestRunner.
     38    """
     39    separator1 = '=' * 70
     40    separator2 = '-' * 70
     41
     42    def __init__(self, stream, descriptions, verbosity):
     43        super(TextTestResult, self).__init__()
     44        self.stream = stream
     45        self.showAll = verbosity > 1
     46        self.dots = verbosity == 1
     47        self.descriptions = descriptions
     48
     49    def getDescription(self, test):
     50        doc_first_line = test.shortDescription()
     51        if self.descriptions and doc_first_line:
     52            return '\n'.join((str(test), doc_first_line))
     53        else:
     54            return str(test)
     55
     56    def startTest(self, test):
     57        super(TextTestResult, self).startTest(test)
     58        if self.showAll:
     59            self.stream.write(self.getDescription(test))
     60            self.stream.write(" ... ")
     61            self.stream.flush()
     62
     63    def addSuccess(self, test):
     64        super(TextTestResult, self).addSuccess(test)
     65        if self.showAll:
     66            self.stream.writeln("ok")
     67        elif self.dots:
     68            self.stream.write('.')
     69            self.stream.flush()
     70
     71    def addError(self, test, err):
     72        super(TextTestResult, self).addError(test, err)
     73        if self.showAll:
     74            self.stream.writeln("ERROR")
     75        elif self.dots:
     76            self.stream.write('E')
     77            self.stream.flush()
     78
     79    def addFailure(self, test, err):
     80        super(TextTestResult, self).addFailure(test, err)
     81        if self.showAll:
     82            self.stream.writeln("FAIL")
     83        elif self.dots:
     84            self.stream.write('F')
     85            self.stream.flush()
     86
     87    def addSkip(self, test, reason):
     88        super(TextTestResult, self).addSkip(test, reason)
     89        if self.showAll:
     90            self.stream.writeln("skipped %r" % (reason,))
     91        elif self.dots:
     92            self.stream.write("s")
     93            self.stream.flush()
     94
     95    def addExpectedFailure(self, test, err):
     96        super(TextTestResult, self).addExpectedFailure(test, err)
     97        if self.showAll:
     98            self.stream.writeln("expected failure")
     99        elif self.dots:
     100            self.stream.write("x")
     101            self.stream.flush()
     102
     103    def addUnexpectedSuccess(self, test):
     104        super(TextTestResult, self).addUnexpectedSuccess(test)
     105        if self.showAll:
     106            self.stream.writeln("unexpected success")
     107        elif self.dots:
     108            self.stream.write("u")
     109            self.stream.flush()
     110
     111    def printErrors(self):
     112        if self.dots or self.showAll:
     113            self.stream.writeln()
     114        self.printErrorList('ERROR', self.errors)
     115        self.printErrorList('FAIL', self.failures)
     116
     117    def printErrorList(self, flavour, errors):
     118        for test, err in errors:
     119            self.stream.writeln(self.separator1)
     120            self.stream.writeln("%s: %s" % (flavour, self.getDescription(test)))
     121            self.stream.writeln(self.separator2)
     122            self.stream.writeln("%s" % err)
     123
     124    def stopTestRun(self):
     125        super(TextTestResult, self).stopTestRun()
     126        self.printErrors()
     127
     128
     129class TextTestRunner(unittest.TextTestRunner):
     130    """A test runner class that displays results in textual form.
     131
     132    It prints out the names of tests as they are run, errors as they
     133    occur, and a summary of the results at the end of the test run.
     134    """
     135    resultclass = TextTestResult
     136
     137    def __init__(self, stream=sys.stderr, descriptions=True, verbosity=1,
     138                    failfast=False, buffer=False, resultclass=None):
     139        self.stream = _WritelnDecorator(stream)
     140        self.descriptions = descriptions
     141        self.verbosity = verbosity
     142        self.failfast = failfast
     143        self.buffer = buffer
     144        if resultclass is not None:
     145            self.resultclass = resultclass
     146
     147    def _makeResult(self):
     148        return self.resultclass(self.stream, self.descriptions, self.verbosity)
     149
     150    def run(self, test):
     151        "Run the given test case or test suite."
     152        result = self._makeResult()
     153        result.failfast = self.failfast
     154        result.buffer = self.buffer
     155        registerResult(result)
     156       
     157        startTime = time.time()
     158        startTestRun = getattr(result, 'startTestRun', None)
     159        if startTestRun is not None:
     160            startTestRun()
     161        try:
     162            test(result)
     163        finally:
     164            stopTestRun = getattr(result, 'stopTestRun', None)
     165            if stopTestRun is not None:
     166                stopTestRun()
     167            else:
     168                result.printErrors()
     169        stopTime = time.time()
     170        timeTaken = stopTime - startTime
     171        if hasattr(result, 'separator2'):
     172            self.stream.writeln(result.separator2)
     173        run = result.testsRun
     174        self.stream.writeln("Ran %d test%s in %.3fs" %
     175                            (run, run != 1 and "s" or "", timeTaken))
     176        self.stream.writeln()
     177       
     178        expectedFails = unexpectedSuccesses = skipped = 0
     179        try:
     180            results = map(len, (result.expectedFailures,
     181                                result.unexpectedSuccesses,
     182                                result.skipped))
     183            expectedFails, unexpectedSuccesses, skipped = results
     184        except AttributeError:
     185            pass
     186        infos = []
     187        if not result.wasSuccessful():
     188            self.stream.write("FAILED")
     189            failed, errored = map(len, (result.failures, result.errors))
     190            if failed:
     191                infos.append("failures=%d" % failed)
     192            if errored:
     193                infos.append("errors=%d" % errored)
     194        else:
     195            self.stream.write("OK")
     196        if skipped:
     197            infos.append("skipped=%d" % skipped)
     198        if expectedFails:
     199            infos.append("expected failures=%d" % expectedFails)
     200        if unexpectedSuccesses:
     201            infos.append("unexpected successes=%d" % unexpectedSuccesses)
     202        if infos:
     203            self.stream.writeln(" (%s)" % (", ".join(infos),))
     204        else:
     205            self.stream.write("\n")
     206        return result
  • django/utils/unittest/suite.py

     
     1"""TestSuite"""
     2
     3import sys
     4import unittest
     5from django.utils.unittest import case, util
     6
     7__unittest = True
     8
     9
     10class BaseTestSuite(unittest.TestSuite):
     11    """A simple test suite that doesn't provide class or module shared fixtures.
     12    """
     13    def __init__(self, tests=()):
     14        self._tests = []
     15        self.addTests(tests)
     16
     17    def __repr__(self):
     18        return "<%s tests=%s>" % (util.strclass(self.__class__), list(self))
     19
     20    def __eq__(self, other):
     21        if not isinstance(other, self.__class__):
     22            return NotImplemented
     23        return list(self) == list(other)
     24
     25    def __ne__(self, other):
     26        return not self == other
     27
     28    # Can't guarantee hash invariant, so flag as unhashable
     29    __hash__ = None
     30
     31    def __iter__(self):
     32        return iter(self._tests)
     33
     34    def countTestCases(self):
     35        cases = 0
     36        for test in self:
     37            cases += test.countTestCases()
     38        return cases
     39
     40    def addTest(self, test):
     41        # sanity checks
     42        if not hasattr(test, '__call__'):
     43            raise TypeError("%r is not callable" % (repr(test),))
     44        if isinstance(test, type) and issubclass(test,
     45                                                 (case.TestCase, TestSuite)):
     46            raise TypeError("TestCases and TestSuites must be instantiated "
     47                            "before passing them to addTest()")
     48        self._tests.append(test)
     49
     50    def addTests(self, tests):
     51        if isinstance(tests, basestring):
     52            raise TypeError("tests must be an iterable of tests, not a string")
     53        for test in tests:
     54            self.addTest(test)
     55
     56    def run(self, result):
     57        for test in self:
     58            if result.shouldStop:
     59                break
     60            test(result)
     61        return result
     62
     63    def __call__(self, *args, **kwds):
     64        return self.run(*args, **kwds)
     65
     66    def debug(self):
     67        """Run the tests without collecting errors in a TestResult"""
     68        for test in self:
     69            test.debug()
     70
     71
     72class TestSuite(BaseTestSuite):
     73    """A test suite is a composite test consisting of a number of TestCases.
     74
     75    For use, create an instance of TestSuite, then add test case instances.
     76    When all tests have been added, the suite can be passed to a test
     77    runner, such as TextTestRunner. It will run the individual test cases
     78    in the order in which they were added, aggregating the results. When
     79    subclassing, do not forget to call the base class constructor.
     80    """
     81   
     82
     83    def run(self, result):
     84        self._wrapped_run(result)
     85        self._tearDownPreviousClass(None, result)
     86        self._handleModuleTearDown(result)
     87        return result
     88
     89    def debug(self):
     90        """Run the tests without collecting errors in a TestResult"""
     91        debug = _DebugResult()
     92        self._wrapped_run(debug, True)
     93        self._tearDownPreviousClass(None, debug)
     94        self._handleModuleTearDown(debug)
     95
     96    ################################
     97    # private methods
     98    def _wrapped_run(self, result, debug=False):
     99        for test in self:
     100            if result.shouldStop:
     101                break
     102           
     103            if _isnotsuite(test):
     104                self._tearDownPreviousClass(test, result)
     105                self._handleModuleFixture(test, result)
     106                self._handleClassSetUp(test, result)
     107                result._previousTestClass = test.__class__
     108               
     109                if (getattr(test.__class__, '_classSetupFailed', False) or
     110                    getattr(result, '_moduleSetUpFailed', False)):
     111                    continue
     112           
     113            if hasattr(test, '_wrapped_run'):
     114                test._wrapped_run(result, debug)
     115            elif not debug:
     116                test(result)
     117            else:
     118                test.debug()
     119   
     120    def _handleClassSetUp(self, test, result):
     121        previousClass = getattr(result, '_previousTestClass', None)
     122        currentClass = test.__class__
     123        if currentClass == previousClass:
     124            return
     125        if result._moduleSetUpFailed:
     126            return
     127        if getattr(currentClass, "__unittest_skip__", False):
     128            return
     129       
     130        try:
     131            currentClass._classSetupFailed = False
     132        except TypeError:
     133            # test may actually be a function
     134            # so its class will be a builtin-type
     135            pass
     136           
     137        setUpClass = getattr(currentClass, 'setUpClass', None)
     138        if setUpClass is not None:
     139            try:
     140                setUpClass()
     141            except Exception, e:
     142                if isinstance(result, _DebugResult):
     143                    raise
     144                currentClass._classSetupFailed = True
     145                className = util.strclass(currentClass)
     146                errorName = 'setUpClass (%s)' % className
     147                self._addClassOrModuleLevelException(result, e, errorName)
     148   
     149    def _get_previous_module(self, result):
     150        previousModule = None
     151        previousClass = getattr(result, '_previousTestClass', None)
     152        if previousClass is not None:
     153            previousModule = previousClass.__module__
     154        return previousModule
     155       
     156       
     157    def _handleModuleFixture(self, test, result):
     158        previousModule = self._get_previous_module(result)
     159        currentModule = test.__class__.__module__
     160        if currentModule == previousModule:
     161            return
     162       
     163        self._handleModuleTearDown(result)
     164
     165       
     166        result._moduleSetUpFailed = False
     167        try:
     168            module = sys.modules[currentModule]
     169        except KeyError:
     170            return
     171        setUpModule = getattr(module, 'setUpModule', None)
     172        if setUpModule is not None:
     173            try:
     174                setUpModule()
     175            except Exception, e:
     176                if isinstance(result, _DebugResult):
     177                    raise
     178                result._moduleSetUpFailed = True
     179                errorName = 'setUpModule (%s)' % currentModule
     180                self._addClassOrModuleLevelException(result, e, errorName)
     181
     182    def _addClassOrModuleLevelException(self, result, exception, errorName):
     183        error = _ErrorHolder(errorName)
     184        addSkip = getattr(result, 'addSkip', None)
     185        if addSkip is not None and isinstance(exception, case.SkipTest):
     186            addSkip(error, str(exception))
     187        else:
     188            result.addError(error, sys.exc_info())
     189   
     190    def _handleModuleTearDown(self, result):
     191        previousModule = self._get_previous_module(result)
     192        if previousModule is None:
     193            return
     194        if result._moduleSetUpFailed:
     195            return
     196           
     197        try:
     198            module = sys.modules[previousModule]
     199        except KeyError:
     200            return
     201
     202        tearDownModule = getattr(module, 'tearDownModule', None)
     203        if tearDownModule is not None:
     204            try:
     205                tearDownModule()
     206            except Exception, e:
     207                if isinstance(result, _DebugResult):
     208                    raise
     209                errorName = 'tearDownModule (%s)' % previousModule
     210                self._addClassOrModuleLevelException(result, e, errorName)
     211   
     212    def _tearDownPreviousClass(self, test, result):
     213        previousClass = getattr(result, '_previousTestClass', None)
     214        currentClass = test.__class__
     215        if currentClass == previousClass:
     216            return
     217        if getattr(previousClass, '_classSetupFailed', False):
     218            return
     219        if getattr(result, '_moduleSetUpFailed', False):
     220            return
     221        if getattr(previousClass, "__unittest_skip__", False):
     222            return
     223       
     224        tearDownClass = getattr(previousClass, 'tearDownClass', None)
     225        if tearDownClass is not None:
     226            try:
     227                tearDownClass()
     228            except Exception, e:
     229                if isinstance(result, _DebugResult):
     230                    raise
     231                className = util.strclass(previousClass)
     232                errorName = 'tearDownClass (%s)' % className
     233                self._addClassOrModuleLevelException(result, e, errorName)
     234
     235
     236class _ErrorHolder(object):
     237    """
     238    Placeholder for a TestCase inside a result. As far as a TestResult
     239    is concerned, this looks exactly like a unit test. Used to insert
     240    arbitrary errors into a test suite run.
     241    """
     242    # Inspired by the ErrorHolder from Twisted:
     243    # http://twistedmatrix.com/trac/browser/trunk/twisted/trial/runner.py
     244
     245    # attribute used by TestResult._exc_info_to_string
     246    failureException = None
     247
     248    def __init__(self, description):
     249        self.description = description
     250
     251    def id(self):
     252        return self.description
     253
     254    def shortDescription(self):
     255        return None
     256
     257    def __repr__(self):
     258        return "<ErrorHolder description=%r>" % (self.description,)
     259
     260    def __str__(self):
     261        return self.id()
     262
     263    def run(self, result):
     264        # could call result.addError(...) - but this test-like object
     265        # shouldn't be run anyway
     266        pass
     267
     268    def __call__(self, result):
     269        return self.run(result)
     270
     271    def countTestCases(self):
     272        return 0
     273
     274def _isnotsuite(test):
     275    "A crude way to tell apart testcases and suites with duck-typing"
     276    try:
     277        iter(test)
     278    except TypeError:
     279        return True
     280    return False
     281
     282
     283class _DebugResult(object):
     284    "Used by the TestSuite to hold previous class when running in debug."
     285    _previousTestClass = None
     286    _moduleSetUpFailed = False
     287    shouldStop = False
  • django/utils/unittest/case.py

     
     1"""Test case implementation"""
     2
     3import sys
     4import difflib
     5import pprint
     6import re
     7import unittest
     8import warnings
     9
     10if sys.version_info[:2] == (2,3):
     11    from sets import Set as set
     12    from sets import ImmutableSet as frozenset
     13
     14from django.utils.unittest import result
     15from django.utils.unittest.util import\
     16    safe_repr, safe_str, strclass,\
     17    unorderable_list_difference
     18
     19from django.utils.unittest.compatibility import wraps
     20
     21__unittest = True
     22
     23
     24DIFF_OMITTED = ('\nDiff is %s characters long. '
     25                 'Set self.maxDiff to None to see it.')
     26
     27class SkipTest(Exception):
     28    """
     29    Raise this exception in a test to skip it.
     30
     31    Usually you can use TestResult.skip() or one of the skipping decorators
     32    instead of raising this directly.
     33    """
     34
     35class _ExpectedFailure(Exception):
     36    """
     37    Raise this when a test is expected to fail.
     38
     39    This is an implementation detail.
     40    """
     41
     42    def __init__(self, exc_info):
     43        # can't use super because Python 2.4 exceptions are old style
     44        Exception.__init__(self)
     45        self.exc_info = exc_info
     46
     47class _UnexpectedSuccess(Exception):
     48    """
     49    The test was supposed to fail, but it didn't!
     50    """
     51
     52def _id(obj):
     53    return obj
     54
     55def skip(reason):
     56    """
     57    Unconditionally skip a test.
     58    """
     59    def decorator(test_item):
     60        if not (isinstance(test_item, type) and issubclass(test_item, TestCase)):
     61            def skip_wrapper(*args, **kwargs):
     62                raise SkipTest(reason)
     63            skip_wrapper = wraps(test_item)(skip_wrapper)
     64            test_item = skip_wrapper
     65       
     66        test_item.__unittest_skip__ = True
     67        test_item.__unittest_skip_why__ = reason
     68        return test_item
     69    return decorator
     70
     71def skipIf(condition, reason):
     72    """
     73    Skip a test if the condition is true.
     74    """
     75    if condition:
     76        return skip(reason)
     77    return _id
     78
     79def skipUnless(condition, reason):
     80    """
     81    Skip a test unless the condition is true.
     82    """
     83    if not condition:
     84        return skip(reason)
     85    return _id
     86
     87
     88def expectedFailure(func):
     89    def wrapper(*args, **kwargs):
     90        try:
     91            func(*args, **kwargs)
     92        except Exception:
     93            raise _ExpectedFailure(sys.exc_info())
     94        raise _UnexpectedSuccess
     95    wrapper = wraps(func)(wrapper)
     96    return wrapper
     97
     98
     99class _AssertRaisesContext(object):
     100    """A context manager used to implement TestCase.assertRaises* methods."""
     101
     102    def __init__(self, expected, test_case, expected_regexp=None):
     103        self.expected = expected
     104        self.failureException = test_case.failureException
     105        self.expected_regexp = expected_regexp
     106
     107    def __enter__(self):
     108        return self
     109
     110    def __exit__(self, exc_type, exc_value, tb):
     111        if exc_type is None:
     112            try:
     113                exc_name = self.expected.__name__
     114            except AttributeError:
     115                exc_name = str(self.expected)
     116            raise self.failureException(
     117                "%s not raised" % (exc_name,))
     118        if not issubclass(exc_type, self.expected):
     119            # let unexpected exceptions pass through
     120            return False
     121        self.exception = exc_value # store for later retrieval
     122        if self.expected_regexp is None:
     123            return True
     124
     125        expected_regexp = self.expected_regexp
     126        if isinstance(expected_regexp, basestring):
     127            expected_regexp = re.compile(expected_regexp)
     128        if not expected_regexp.search(str(exc_value)):
     129            raise self.failureException('"%s" does not match "%s"' %
     130                     (expected_regexp.pattern, str(exc_value)))
     131        return True
     132
     133
     134class _TypeEqualityDict(object):
     135   
     136    def __init__(self, testcase):
     137        self.testcase = testcase
     138        self._store = {}
     139   
     140    def __setitem__(self, key, value):
     141        self._store[key] = value
     142   
     143    def __getitem__(self, key):
     144        value = self._store[key]
     145        if isinstance(value, basestring):
     146            return getattr(self.testcase, value)
     147        return value
     148   
     149    def get(self, key, default=None):
     150        if key in self._store:
     151            return self[key]
     152        return default
     153
     154
     155class TestCase(unittest.TestCase):
     156    """A class whose instances are single test cases.
     157
     158    By default, the test code itself should be placed in a method named
     159    'runTest'.
     160
     161    If the fixture may be used for many test cases, create as
     162    many test methods as are needed. When instantiating such a TestCase
     163    subclass, specify in the constructor arguments the name of the test method
     164    that the instance is to execute.
     165
     166    Test authors should subclass TestCase for their own tests. Construction
     167    and deconstruction of the test's environment ('fixture') can be
     168    implemented by overriding the 'setUp' and 'tearDown' methods respectively.
     169
     170    If it is necessary to override the __init__ method, the base class
     171    __init__ method must always be called. It is important that subclasses
     172    should not change the signature of their __init__ method, since instances
     173    of the classes are instantiated automatically by parts of the framework
     174    in order to be run.
     175    """
     176
     177    # This attribute determines which exception will be raised when
     178    # the instance's assertion methods fail; test methods raising this
     179    # exception will be deemed to have 'failed' rather than 'errored'
     180
     181    failureException = AssertionError
     182
     183    # This attribute sets the maximum length of a diff in failure messages
     184    # by assert methods using difflib. It is looked up as an instance attribute
     185    # so can be configured by individual tests if required.
     186
     187    maxDiff = 80*8
     188
     189    # This attribute determines whether long messages (including repr of
     190    # objects used in assert methods) will be printed on failure in *addition*
     191    # to any explicit message passed.
     192
     193    longMessage = True
     194   
     195    # Attribute used by TestSuite for classSetUp
     196   
     197    _classSetupFailed = False
     198
     199    def __init__(self, methodName='runTest'):
     200        """Create an instance of the class that will use the named test
     201           method when executed. Raises a ValueError if the instance does
     202           not have a method with the specified name.
     203        """
     204        self._testMethodName = methodName
     205        self._resultForDoCleanups = None
     206        try:
     207            testMethod = getattr(self, methodName)
     208        except AttributeError:
     209            raise ValueError("no such test method in %s: %s" % \
     210                  (self.__class__, methodName))
     211        self._testMethodDoc = testMethod.__doc__
     212        self._cleanups = []
     213
     214        # Map types to custom assertEqual functions that will compare
     215        # instances of said type in more detail to generate a more useful
     216        # error message.
     217        self._type_equality_funcs = _TypeEqualityDict(self)
     218        self.addTypeEqualityFunc(dict, 'assertDictEqual')
     219        self.addTypeEqualityFunc(list, 'assertListEqual')
     220        self.addTypeEqualityFunc(tuple, 'assertTupleEqual')
     221        self.addTypeEqualityFunc(set, 'assertSetEqual')
     222        self.addTypeEqualityFunc(frozenset, 'assertSetEqual')
     223        self.addTypeEqualityFunc(unicode, 'assertMultiLineEqual')
     224
     225    def addTypeEqualityFunc(self, typeobj, function):
     226        """Add a type specific assertEqual style function to compare a type.
     227
     228        This method is for use by TestCase subclasses that need to register
     229        their own type equality functions to provide nicer error messages.
     230
     231        Args:
     232            typeobj: The data type to call this function on when both values
     233                    are of the same type in assertEqual().
     234            function: The callable taking two arguments and an optional
     235                    msg= argument that raises self.failureException with a
     236                    useful error message when the two arguments are not equal.
     237        """
     238        self._type_equality_funcs[typeobj] = function
     239
     240    def addCleanup(self, function, *args, **kwargs):
     241        """Add a function, with arguments, to be called when the test is
     242        completed. Functions added are called on a LIFO basis and are
     243        called after tearDown on test failure or success.
     244
     245        Cleanup items are called even if setUp fails (unlike tearDown)."""
     246        self._cleanups.append((function, args, kwargs))
     247
     248    def setUp(self):
     249        "Hook method for setting up the test fixture before exercising it."
     250   
     251    def setUpClass(cls):
     252        "Hook method for setting up class fixture before running tests in the class."
     253    setUpClass = classmethod(setUpClass)
     254   
     255    def tearDownClass(cls):
     256        "Hook method for deconstructing the class fixture after running all tests in the class."
     257    tearDownClass = classmethod(tearDownClass)
     258   
     259    def tearDown(self):
     260        "Hook method for deconstructing the test fixture after testing it."
     261
     262    def countTestCases(self):
     263        return 1
     264
     265    def defaultTestResult(self):
     266        return result.TestResult()
     267
     268    def shortDescription(self):
     269        """Returns a one-line description of the test, or None if no
     270        description has been provided.
     271
     272        The default implementation of this method returns the first line of
     273        the specified test method's docstring.
     274        """
     275        doc = self._testMethodDoc
     276        return doc and doc.split("\n")[0].strip() or None
     277
     278
     279    def id(self):
     280        return "%s.%s" % (strclass(self.__class__), self._testMethodName)
     281
     282    def __eq__(self, other):
     283        if type(self) is not type(other):
     284            return NotImplemented
     285
     286        return self._testMethodName == other._testMethodName
     287
     288    def __ne__(self, other):
     289        return not self == other
     290
     291    def __hash__(self):
     292        return hash((type(self), self._testMethodName))
     293
     294    def __str__(self):
     295        return "%s (%s)" % (self._testMethodName, strclass(self.__class__))
     296
     297    def __repr__(self):
     298        return "<%s testMethod=%s>" % \
     299               (strclass(self.__class__), self._testMethodName)
     300   
     301    def _addSkip(self, result, reason):
     302        addSkip = getattr(result, 'addSkip', None)
     303        if addSkip is not None:
     304            addSkip(self, reason)
     305        else:
     306            warnings.warn("Use of a TestResult without an addSkip method is deprecated",
     307                          DeprecationWarning, 2)
     308            result.addSuccess(self)
     309
     310    def run(self, result=None):
     311        orig_result = result
     312        if result is None:
     313            result = self.defaultTestResult()
     314            startTestRun = getattr(result, 'startTestRun', None)
     315            if startTestRun is not None:
     316                startTestRun()
     317
     318        self._resultForDoCleanups = result
     319        result.startTest(self)
     320       
     321        testMethod = getattr(self, self._testMethodName)
     322       
     323        if (getattr(self.__class__, "__unittest_skip__", False) or
     324            getattr(testMethod, "__unittest_skip__", False)):
     325            # If the class or method was skipped.
     326            try:
     327                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
     328                            or getattr(testMethod, '__unittest_skip_why__', ''))
     329                self._addSkip(result, skip_why)
     330            finally:
     331                result.stopTest(self)
     332            return
     333        try:
     334            success = False
     335            try:
     336                self.setUp()
     337            except SkipTest, e:
     338                self._addSkip(result, str(e))
     339            except Exception:
     340                result.addError(self, sys.exc_info())
     341            else:
     342                try:
     343                    testMethod()
     344                except self.failureException:
     345                    result.addFailure(self, sys.exc_info())
     346                except _ExpectedFailure, e:
     347                    addExpectedFailure = getattr(result, 'addExpectedFailure', None)
     348                    if addExpectedFailure is not None:
     349                        addExpectedFailure(self, e.exc_info)
     350                    else:
     351                        warnings.warn("Use of a TestResult without an addExpectedFailure method is deprecated",
     352                                      DeprecationWarning)
     353                        result.addSuccess(self)
     354                except _UnexpectedSuccess:
     355                    addUnexpectedSuccess = getattr(result, 'addUnexpectedSuccess', None)
     356                    if addUnexpectedSuccess is not None:
     357                        addUnexpectedSuccess(self)
     358                    else:
     359                        warnings.warn("Use of a TestResult without an addUnexpectedSuccess method is deprecated",
     360                                      DeprecationWarning)
     361                        result.addFailure(self, sys.exc_info())
     362                except SkipTest, e:
     363                    self._addSkip(result, str(e))
     364                except Exception:
     365                    result.addError(self, sys.exc_info())
     366                else:
     367                    success = True
     368
     369                try:
     370                    self.tearDown()
     371                except Exception:
     372                    result.addError(self, sys.exc_info())
     373                    success = False
     374
     375            cleanUpSuccess = self.doCleanups()
     376            success = success and cleanUpSuccess
     377            if success:
     378                result.addSuccess(self)
     379        finally:
     380            result.stopTest(self)
     381            if orig_result is None:
     382                stopTestRun = getattr(result, 'stopTestRun', None)
     383                if stopTestRun is not None:
     384                    stopTestRun()
     385
     386    def doCleanups(self):
     387        """Execute all cleanup functions. Normally called for you after
     388        tearDown."""
     389        result = self._resultForDoCleanups
     390        ok = True
     391        while self._cleanups:
     392            function, args, kwargs = self._cleanups.pop(-1)
     393            try:
     394                function(*args, **kwargs)
     395            except Exception:
     396                ok = False
     397                result.addError(self, sys.exc_info())
     398        return ok
     399
     400    def __call__(self, *args, **kwds):
     401        return self.run(*args, **kwds)
     402
     403    def debug(self):
     404        """Run the test without collecting errors in a TestResult"""
     405        self.setUp()
     406        getattr(self, self._testMethodName)()
     407        self.tearDown()
     408        while self._cleanups:
     409            function, args, kwargs = self._cleanups.pop(-1)
     410            function(*args, **kwargs)
     411
     412    def skipTest(self, reason):
     413        """Skip this test."""
     414        raise SkipTest(reason)
     415
     416    def fail(self, msg=None):
     417        """Fail immediately, with the given message."""
     418        raise self.failureException(msg)
     419
     420    def assertFalse(self, expr, msg=None):
     421        "Fail the test if the expression is true."
     422        if expr:
     423            msg = self._formatMessage(msg, "%s is not False" % safe_repr(expr))
     424            raise self.failureException(msg)
     425
     426    def assertTrue(self, expr, msg=None):
     427        """Fail the test unless the expression is true."""
     428        if not expr:
     429            msg = self._formatMessage(msg, "%s is not True" % safe_repr(expr))
     430            raise self.failureException(msg)
     431
     432    def _formatMessage(self, msg, standardMsg):
     433        """Honour the longMessage attribute when generating failure messages.
     434        If longMessage is False this means:
     435        * Use only an explicit message if it is provided
     436        * Otherwise use the standard message for the assert
     437
     438        If longMessage is True:
     439        * Use the standard message
     440        * If an explicit message is provided, plus ' : ' and the explicit message
     441        """
     442        if not self.longMessage:
     443            return msg or standardMsg
     444        if msg is None:
     445            return standardMsg
     446        try:
     447            return '%s : %s' % (standardMsg, msg)
     448        except UnicodeDecodeError:
     449            return '%s : %s' % (safe_str(standardMsg), safe_str(msg))
     450
     451
     452    def assertRaises(self, excClass, callableObj=None, *args, **kwargs):
     453        """Fail unless an exception of class excClass is thrown
     454           by callableObj when invoked with arguments args and keyword
     455           arguments kwargs. If a different type of exception is
     456           thrown, it will not be caught, and the test case will be
     457           deemed to have suffered an error, exactly as for an
     458           unexpected exception.
     459
     460           If called with callableObj omitted or None, will return a
     461           context object used like this::
     462
     463                with self.assertRaises(SomeException):
     464                    do_something()
     465
     466           The context manager keeps a reference to the exception as
     467           the 'exception' attribute. This allows you to inspect the
     468           exception after the assertion::
     469
     470               with self.assertRaises(SomeException) as cm:
     471                   do_something()
     472               the_exception = cm.exception
     473               self.assertEqual(the_exception.error_code, 3)
     474        """
     475        if callableObj is None:
     476            return _AssertRaisesContext(excClass, self)
     477        try:
     478            callableObj(*args, **kwargs)
     479        except excClass:
     480            return
     481       
     482        if hasattr(excClass,'__name__'):
     483            excName = excClass.__name__
     484        else:
     485            excName = str(excClass)
     486        raise self.failureException, "%s not raised" % excName
     487
     488    def _getAssertEqualityFunc(self, first, second):
     489        """Get a detailed comparison function for the types of the two args.
     490
     491        Returns: A callable accepting (first, second, msg=None) that will
     492        raise a failure exception if first != second with a useful human
     493        readable error message for those types.
     494        """
     495        #
     496        # NOTE(gregory.p.smith): I considered isinstance(first, type(second))
     497        # and vice versa.  I opted for the conservative approach in case
     498        # subclasses are not intended to be compared in detail to their super
     499        # class instances using a type equality func.  This means testing
     500        # subtypes won't automagically use the detailed comparison.  Callers
     501        # should use their type specific assertSpamEqual method to compare
     502        # subclasses if the detailed comparison is desired and appropriate.
     503        # See the discussion in http://bugs.python.org/issue2578.
     504        #
     505        if type(first) is type(second):
     506            asserter = self._type_equality_funcs.get(type(first))
     507            if asserter is not None:
     508                return asserter
     509
     510        return self._baseAssertEqual
     511
     512    def _baseAssertEqual(self, first, second, msg=None):
     513        """The default assertEqual implementation, not type specific."""
     514        if not first == second:
     515            standardMsg = '%s != %s' % (safe_repr(first), safe_repr(second))
     516            msg = self._formatMessage(msg, standardMsg)
     517            raise self.failureException(msg)
     518
     519    def assertEqual(self, first, second, msg=None):
     520        """Fail if the two objects are unequal as determined by the '=='
     521           operator.
     522        """
     523        assertion_func = self._getAssertEqualityFunc(first, second)
     524        assertion_func(first, second, msg=msg)
     525
     526    def assertNotEqual(self, first, second, msg=None):
     527        """Fail if the two objects are equal as determined by the '=='
     528           operator.
     529        """
     530        if not first != second:
     531            msg = self._formatMessage(msg, '%s == %s' % (safe_repr(first),
     532                                                           safe_repr(second)))
     533            raise self.failureException(msg)
     534
     535    def assertAlmostEqual(self, first, second, places=None, msg=None, delta=None):
     536        """Fail if the two objects are unequal as determined by their
     537           difference rounded to the given number of decimal places
     538           (default 7) and comparing to zero, or by comparing that the
     539           between the two objects is more than the given delta.
     540
     541           Note that decimal places (from zero) are usually not the same
     542           as significant digits (measured from the most signficant digit).
     543
     544           If the two objects compare equal then they will automatically
     545           compare almost equal.
     546        """
     547        if first == second:
     548            # shortcut
     549            return
     550        if delta is not None and places is not None:
     551            raise TypeError("specify delta or places not both")
     552       
     553        if delta is not None:
     554            if abs(first - second) <= delta:
     555                return
     556       
     557            standardMsg = '%s != %s within %s delta' % (safe_repr(first),
     558                                                        safe_repr(second),
     559                                                        safe_repr(delta))
     560        else:
     561            if places is None:
     562                places = 7
     563               
     564            if round(abs(second-first), places) == 0:
     565                return
     566       
     567            standardMsg = '%s != %s within %r places' % (safe_repr(first),
     568                                                          safe_repr(second),
     569                                                          places)
     570        msg = self._formatMessage(msg, standardMsg)
     571        raise self.failureException(msg)
     572
     573    def assertNotAlmostEqual(self, first, second, places=None, msg=None, delta=None):
     574        """Fail if the two objects are equal as determined by their
     575           difference rounded to the given number of decimal places
     576           (default 7) and comparing to zero, or by comparing that the
     577           between the two objects is less than the given delta.
     578
     579           Note that decimal places (from zero) are usually not the same
     580           as significant digits (measured from the most signficant digit).
     581
     582           Objects that are equal automatically fail.
     583        """
     584        if delta is not None and places is not None:
     585            raise TypeError("specify delta or places not both")
     586        if delta is not None:
     587            if not (first == second) and abs(first - second) > delta:
     588                return
     589            standardMsg = '%s == %s within %s delta' % (safe_repr(first),
     590                                                        safe_repr(second),
     591                                                        safe_repr(delta))
     592        else:
     593            if places is None:
     594                places = 7
     595            if not (first == second) and round(abs(second-first), places) != 0:
     596                return
     597            standardMsg = '%s == %s within %r places' % (safe_repr(first),
     598                                                         safe_repr(second),
     599                                                         places)
     600
     601        msg = self._formatMessage(msg, standardMsg)
     602        raise self.failureException(msg)
     603
     604    # Synonyms for assertion methods
     605
     606    # The plurals are undocumented.  Keep them that way to discourage use.
     607    # Do not add more.  Do not remove.
     608    # Going through a deprecation cycle on these would annoy many people.
     609    assertEquals = assertEqual
     610    assertNotEquals = assertNotEqual
     611    assertAlmostEquals = assertAlmostEqual
     612    assertNotAlmostEquals = assertNotAlmostEqual
     613    assert_ = assertTrue
     614
     615    # These fail* assertion method names are pending deprecation and will
     616    # be a DeprecationWarning in 3.2; http://bugs.python.org/issue2578
     617    def _deprecate(original_func):
     618        def deprecated_func(*args, **kwargs):
     619            warnings.warn(
     620                ('Please use %s instead.' % original_func.__name__),
     621                PendingDeprecationWarning, 2)
     622            return original_func(*args, **kwargs)
     623        return deprecated_func
     624
     625    failUnlessEqual = _deprecate(assertEqual)
     626    failIfEqual = _deprecate(assertNotEqual)
     627    failUnlessAlmostEqual = _deprecate(assertAlmostEqual)
     628    failIfAlmostEqual = _deprecate(assertNotAlmostEqual)
     629    failUnless = _deprecate(assertTrue)
     630    failUnlessRaises = _deprecate(assertRaises)
     631    failIf = _deprecate(assertFalse)
     632
     633    def assertSequenceEqual(self, seq1, seq2,
     634                            msg=None, seq_type=None, max_diff=80*8):
     635        """An equality assertion for ordered sequences (like lists and tuples).
     636
     637        For the purposes of this function, a valid ordered sequence type is one
     638        which can be indexed, has a length, and has an equality operator.
     639
     640        Args:
     641            seq1: The first sequence to compare.
     642            seq2: The second sequence to compare.
     643            seq_type: The expected datatype of the sequences, or None if no
     644                    datatype should be enforced.
     645            msg: Optional message to use on failure instead of a list of
     646                    differences.
     647            max_diff: Maximum size off the diff, larger diffs are not shown
     648        """
     649        if seq_type is not None:
     650            seq_type_name = seq_type.__name__
     651            if not isinstance(seq1, seq_type):
     652                raise self.failureException('First sequence is not a %s: %s'
     653                                            % (seq_type_name, safe_repr(seq1)))
     654            if not isinstance(seq2, seq_type):
     655                raise self.failureException('Second sequence is not a %s: %s'
     656                                            % (seq_type_name, safe_repr(seq2)))
     657        else:
     658            seq_type_name = "sequence"
     659
     660        differing = None
     661        try:
     662            len1 = len(seq1)
     663        except (TypeError, NotImplementedError):
     664            differing = 'First %s has no length.    Non-sequence?' % (
     665                    seq_type_name)
     666
     667        if differing is None:
     668            try:
     669                len2 = len(seq2)
     670            except (TypeError, NotImplementedError):
     671                differing = 'Second %s has no length.    Non-sequence?' % (
     672                        seq_type_name)
     673
     674        if differing is None:
     675            if seq1 == seq2:
     676                return
     677
     678            seq1_repr = repr(seq1)
     679            seq2_repr = repr(seq2)
     680            if len(seq1_repr) > 30:
     681                seq1_repr = seq1_repr[:30] + '...'
     682            if len(seq2_repr) > 30:
     683                seq2_repr = seq2_repr[:30] + '...'
     684            elements = (seq_type_name.capitalize(), seq1_repr, seq2_repr)
     685            differing = '%ss differ: %s != %s\n' % elements
     686
     687            for i in xrange(min(len1, len2)):
     688                try:
     689                    item1 = seq1[i]
     690                except (TypeError, IndexError, NotImplementedError):
     691                    differing += ('\nUnable to index element %d of first %s\n' %
     692                                 (i, seq_type_name))
     693                    break
     694
     695                try:
     696                    item2 = seq2[i]
     697                except (TypeError, IndexError, NotImplementedError):
     698                    differing += ('\nUnable to index element %d of second %s\n' %
     699                                 (i, seq_type_name))
     700                    break
     701
     702                if item1 != item2:
     703                    differing += ('\nFirst differing element %d:\n%s\n%s\n' %
     704                                 (i, item1, item2))
     705                    break
     706            else:
     707                if (len1 == len2 and seq_type is None and
     708                    type(seq1) != type(seq2)):
     709                    # The sequences are the same, but have differing types.
     710                    return
     711
     712            if len1 > len2:
     713                differing += ('\nFirst %s contains %d additional '
     714                             'elements.\n' % (seq_type_name, len1 - len2))
     715                try:
     716                    differing += ('First extra element %d:\n%s\n' %
     717                                  (len2, seq1[len2]))
     718                except (TypeError, IndexError, NotImplementedError):
     719                    differing += ('Unable to index element %d '
     720                                  'of first %s\n' % (len2, seq_type_name))
     721            elif len1 < len2:
     722                differing += ('\nSecond %s contains %d additional '
     723                             'elements.\n' % (seq_type_name, len2 - len1))
     724                try:
     725                    differing += ('First extra element %d:\n%s\n' %
     726                                  (len1, seq2[len1]))
     727                except (TypeError, IndexError, NotImplementedError):
     728                    differing += ('Unable to index element %d '
     729                                  'of second %s\n' % (len1, seq_type_name))
     730        standardMsg = differing
     731        diffMsg = '\n' + '\n'.join(
     732            difflib.ndiff(pprint.pformat(seq1).splitlines(),
     733                          pprint.pformat(seq2).splitlines()))
     734
     735        standardMsg = self._truncateMessage(standardMsg, diffMsg)
     736        msg = self._formatMessage(msg, standardMsg)
     737        self.fail(msg)
     738
     739    def _truncateMessage(self, message, diff):
     740        max_diff = self.maxDiff
     741        if max_diff is None or len(diff) <= max_diff:
     742            return message + diff
     743        return message + (DIFF_OMITTED % len(diff))
     744
     745    def assertListEqual(self, list1, list2, msg=None):
     746        """A list-specific equality assertion.
     747
     748        Args:
     749            list1: The first list to compare.
     750            list2: The second list to compare.
     751            msg: Optional message to use on failure instead of a list of
     752                    differences.
     753
     754        """
     755        self.assertSequenceEqual(list1, list2, msg, seq_type=list)
     756
     757    def assertTupleEqual(self, tuple1, tuple2, msg=None):
     758        """A tuple-specific equality assertion.
     759
     760        Args:
     761            tuple1: The first tuple to compare.
     762            tuple2: The second tuple to compare.
     763            msg: Optional message to use on failure instead of a list of
     764                    differences.
     765        """
     766        self.assertSequenceEqual(tuple1, tuple2, msg, seq_type=tuple)
     767
     768    def assertSetEqual(self, set1, set2, msg=None):
     769        """A set-specific equality assertion.
     770
     771        Args:
     772            set1: The first set to compare.
     773            set2: The second set to compare.
     774            msg: Optional message to use on failure instead of a list of
     775                    differences.
     776
     777        assertSetEqual uses ducktyping to support
     778        different types of sets, and is optimized for sets specifically
     779        (parameters must support a difference method).
     780        """
     781        try:
     782            difference1 = set1.difference(set2)
     783        except TypeError, e:
     784            self.fail('invalid type when attempting set difference: %s' % e)
     785        except AttributeError, e:
     786            self.fail('first argument does not support set difference: %s' % e)
     787
     788        try:
     789            difference2 = set2.difference(set1)
     790        except TypeError, e:
     791            self.fail('invalid type when attempting set difference: %s' % e)
     792        except AttributeError, e:
     793            self.fail('second argument does not support set difference: %s' % e)
     794
     795        if not (difference1 or difference2):
     796            return
     797
     798        lines = []
     799        if difference1:
     800            lines.append('Items in the first set but not the second:')
     801            for item in difference1:
     802                lines.append(repr(item))
     803        if difference2:
     804            lines.append('Items in the second set but not the first:')
     805            for item in difference2:
     806                lines.append(repr(item))
     807
     808        standardMsg = '\n'.join(lines)
     809        self.fail(self._formatMessage(msg, standardMsg))
     810
     811    def assertIn(self, member, container, msg=None):
     812        """Just like self.assertTrue(a in b), but with a nicer default message."""
     813        if member not in container:
     814            standardMsg = '%s not found in %s' % (safe_repr(member),
     815                                                   safe_repr(container))
     816            self.fail(self._formatMessage(msg, standardMsg))
     817
     818    def assertNotIn(self, member, container, msg=None):
     819        """Just like self.assertTrue(a not in b), but with a nicer default message."""
     820        if member in container:
     821            standardMsg = '%s unexpectedly found in %s' % (safe_repr(member),
     822                                                            safe_repr(container))
     823            self.fail(self._formatMessage(msg, standardMsg))
     824
     825    def assertIs(self, expr1, expr2, msg=None):
     826        """Just like self.assertTrue(a is b), but with a nicer default message."""
     827        if expr1 is not expr2:
     828            standardMsg = '%s is not %s' % (safe_repr(expr1), safe_repr(expr2))
     829            self.fail(self._formatMessage(msg, standardMsg))
     830
     831    def assertIsNot(self, expr1, expr2, msg=None):
     832        """Just like self.assertTrue(a is not b), but with a nicer default message."""
     833        if expr1 is expr2:
     834            standardMsg = 'unexpectedly identical: %s' % (safe_repr(expr1),)
     835            self.fail(self._formatMessage(msg, standardMsg))
     836
     837    def assertDictEqual(self, d1, d2, msg=None):
     838        self.assert_(isinstance(d1, dict), 'First argument is not a dictionary')
     839        self.assert_(isinstance(d2, dict), 'Second argument is not a dictionary')
     840
     841        if d1 != d2:
     842            standardMsg = '%s != %s' % (safe_repr(d1, True), safe_repr(d2, True))
     843            diff = ('\n' + '\n'.join(difflib.ndiff(
     844                           pprint.pformat(d1).splitlines(),
     845                           pprint.pformat(d2).splitlines())))
     846            standardMsg = self._truncateMessage(standardMsg, diff)
     847            self.fail(self._formatMessage(msg, standardMsg))
     848
     849    def assertDictContainsSubset(self, expected, actual, msg=None):
     850        """Checks whether actual is a superset of expected."""
     851        missing = []
     852        mismatched = []
     853        for key, value in expected.iteritems():
     854            if key not in actual:
     855                missing.append(key)
     856            else:
     857                try:
     858                    are_equal = (value == actual[key])
     859                except UnicodeDecodeError:
     860                    are_equal = False
     861                if not are_equal:
     862                    mismatched.append('%s, expected: %s, actual: %s' %
     863                                      (safe_repr(key), safe_repr(value),
     864                                       safe_repr(actual[key])))
     865
     866        if not (missing or mismatched):
     867            return
     868
     869        standardMsg = ''
     870        if missing:
     871            standardMsg = 'Missing: %s' % ','.join([safe_repr(m) for m in
     872                                                    missing])
     873        if mismatched:
     874            if standardMsg:
     875                standardMsg += '; '
     876            standardMsg += 'Mismatched values: %s' % ','.join(mismatched)
     877
     878        self.fail(self._formatMessage(msg, standardMsg))
     879
     880    def assertItemsEqual(self, expected_seq, actual_seq, msg=None):
     881        """An unordered sequence specific comparison. It asserts that
     882        expected_seq and actual_seq contain the same elements. It is
     883        the equivalent of::
     884       
     885            self.assertEqual(sorted(expected_seq), sorted(actual_seq))
     886
     887        Raises with an error message listing which elements of expected_seq
     888        are missing from actual_seq and vice versa if any.
     889       
     890        Asserts that each element has the same count in both sequences.
     891        Example:
     892            - [0, 1, 1] and [1, 0, 1] compare equal.
     893            - [0, 0, 1] and [0, 1] compare unequal.
     894        """
     895        try:
     896           
     897            expected = expected_seq[:]
     898            expected.sort()
     899            actual = actual_seq[:]
     900            actual.sort()
     901        except (TypeError, AttributeError):
     902            # Unsortable items (example: set(), complex(), ...)
     903            expected = list(expected_seq)
     904            actual = list(actual_seq)
     905            missing, unexpected = unorderable_list_difference(
     906                expected, actual, ignore_duplicate=False
     907            )
     908        else:
     909            return self.assertSequenceEqual(expected, actual, msg=msg)
     910
     911        errors = []
     912        if missing:
     913            errors.append('Expected, but missing:\n    %s' %
     914                           safe_repr(missing))
     915        if unexpected:
     916            errors.append('Unexpected, but present:\n    %s' %
     917                           safe_repr(unexpected))
     918        if errors:
     919            standardMsg = '\n'.join(errors)
     920            self.fail(self._formatMessage(msg, standardMsg))
     921
     922    def assertMultiLineEqual(self, first, second, msg=None):
     923        """Assert that two multi-line strings are equal."""
     924        self.assert_(isinstance(first, basestring), (
     925                'First argument is not a string'))
     926        self.assert_(isinstance(second, basestring), (
     927                'Second argument is not a string'))
     928
     929        if first != second:
     930            standardMsg = '%s != %s' % (safe_repr(first, True), safe_repr(second, True))
     931            diff = '\n' + ''.join(difflib.ndiff(first.splitlines(True),
     932                                                       second.splitlines(True)))
     933            standardMsg = self._truncateMessage(standardMsg, diff)
     934            self.fail(self._formatMessage(msg, standardMsg))
     935
     936    def assertLess(self, a, b, msg=None):
     937        """Just like self.assertTrue(a < b), but with a nicer default message."""
     938        if not a < b:
     939            standardMsg = '%s not less than %s' % (safe_repr(a), safe_repr(b))
     940            self.fail(self._formatMessage(msg, standardMsg))
     941
     942    def assertLessEqual(self, a, b, msg=None):
     943        """Just like self.assertTrue(a <= b), but with a nicer default message."""
     944        if not a <= b:
     945            standardMsg = '%s not less than or equal to %s' % (safe_repr(a), safe_repr(b))
     946            self.fail(self._formatMessage(msg, standardMsg))
     947
     948    def assertGreater(self, a, b, msg=None):
     949        """Just like self.assertTrue(a > b), but with a nicer default message."""
     950        if not a > b:
     951            standardMsg = '%s not greater than %s' % (safe_repr(a), safe_repr(b))
     952            self.fail(self._formatMessage(msg, standardMsg))
     953
     954    def assertGreaterEqual(self, a, b, msg=None):
     955        """Just like self.assertTrue(a >= b), but with a nicer default message."""
     956        if not a >= b:
     957            standardMsg = '%s not greater than or equal to %s' % (safe_repr(a), safe_repr(b))
     958            self.fail(self._formatMessage(msg, standardMsg))
     959
     960    def assertIsNone(self, obj, msg=None):
     961        """Same as self.assertTrue(obj is None), with a nicer default message."""
     962        if obj is not None:
     963            standardMsg = '%s is not None' % (safe_repr(obj),)
     964            self.fail(self._formatMessage(msg, standardMsg))
     965
     966    def assertIsNotNone(self, obj, msg=None):
     967        """Included for symmetry with assertIsNone."""
     968        if obj is None:
     969            standardMsg = 'unexpectedly None'
     970            self.fail(self._formatMessage(msg, standardMsg))
     971
     972    def assertIsInstance(self, obj, cls, msg=None):
     973        """Same as self.assertTrue(isinstance(obj, cls)), with a nicer
     974        default message."""
     975        if not isinstance(obj, cls):
     976            standardMsg = '%s is not an instance of %r' % (safe_repr(obj), cls)
     977            self.fail(self._formatMessage(msg, standardMsg))
     978
     979    def assertNotIsInstance(self, obj, cls, msg=None):
     980        """Included for symmetry with assertIsInstance."""
     981        if isinstance(obj, cls):
     982            standardMsg = '%s is an instance of %r' % (safe_repr(obj), cls)
     983            self.fail(self._formatMessage(msg, standardMsg))
     984
     985    def assertRaisesRegexp(self, expected_exception, expected_regexp,
     986                           callable_obj=None, *args, **kwargs):
     987        """Asserts that the message in a raised exception matches a regexp.
     988
     989        Args:
     990            expected_exception: Exception class expected to be raised.
     991            expected_regexp: Regexp (re pattern object or string) expected
     992                    to be found in error message.
     993            callable_obj: Function to be called.
     994            args: Extra args.
     995            kwargs: Extra kwargs.
     996        """
     997        if callable_obj is None:
     998            return _AssertRaisesContext(expected_exception, self, expected_regexp)
     999        try:
     1000            callable_obj(*args, **kwargs)
     1001        except expected_exception, exc_value:
     1002            if isinstance(expected_regexp, basestring):
     1003                expected_regexp = re.compile(expected_regexp)
     1004            if not expected_regexp.search(str(exc_value)):
     1005                raise self.failureException('"%s" does not match "%s"' %
     1006                         (expected_regexp.pattern, str(exc_value)))
     1007        else:
     1008            if hasattr(expected_exception, '__name__'):
     1009                excName = expected_exception.__name__
     1010            else:
     1011                excName = str(expected_exception)
     1012            raise self.failureException, "%s not raised" % excName
     1013
     1014
     1015    def assertRegexpMatches(self, text, expected_regexp, msg=None):
     1016        """Fail the test unless the text matches the regular expression."""
     1017        if isinstance(expected_regexp, basestring):
     1018            expected_regexp = re.compile(expected_regexp)
     1019        if not expected_regexp.search(text):
     1020            msg = msg or "Regexp didn't match"
     1021            msg = '%s: %r not found in %r' % (msg, expected_regexp.pattern, text)
     1022            raise self.failureException(msg)
     1023
     1024    def assertNotRegexpMatches(self, text, unexpected_regexp, msg=None):
     1025        """Fail the test if the text matches the regular expression."""
     1026        if isinstance(unexpected_regexp, basestring):
     1027            unexpected_regexp = re.compile(unexpected_regexp)
     1028        match = unexpected_regexp.search(text)
     1029        if match:
     1030            msg = msg or "Regexp matched"
     1031            msg = '%s: %r matches %r in %r' % (msg,
     1032                                               text[match.start():match.end()],
     1033                                               unexpected_regexp.pattern,
     1034                                               text)
     1035            raise self.failureException(msg)
     1036
     1037class FunctionTestCase(TestCase):
     1038    """A test case that wraps a test function.
     1039
     1040    This is useful for slipping pre-existing test functions into the
     1041    unittest framework. Optionally, set-up and tidy-up functions can be
     1042    supplied. As with TestCase, the tidy-up ('tearDown') function will
     1043    always be called if the set-up ('setUp') function ran successfully.
     1044    """
     1045
     1046    def __init__(self, testFunc, setUp=None, tearDown=None, description=None):
     1047        super(FunctionTestCase, self).__init__()
     1048        self._setUpFunc = setUp
     1049        self._tearDownFunc = tearDown
     1050        self._testFunc = testFunc
     1051        self._description = description
     1052
     1053    def setUp(self):
     1054        if self._setUpFunc is not None:
     1055            self._setUpFunc()
     1056
     1057    def tearDown(self):
     1058        if self._tearDownFunc is not None:
     1059            self._tearDownFunc()
     1060
     1061    def runTest(self):
     1062        self._testFunc()
     1063
     1064    def id(self):
     1065        return self._testFunc.__name__
     1066
     1067    def __eq__(self, other):
     1068        if not isinstance(other, self.__class__):
     1069            return NotImplemented
     1070
     1071        return self._setUpFunc == other._setUpFunc and \
     1072               self._tearDownFunc == other._tearDownFunc and \
     1073               self._testFunc == other._testFunc and \
     1074               self._description == other._description
     1075
     1076    def __ne__(self, other):
     1077        return not self == other
     1078
     1079    def __hash__(self):
     1080        return hash((type(self), self._setUpFunc, self._tearDownFunc,
     1081                     self._testFunc, self._description))
     1082
     1083    def __str__(self):
     1084        return "%s (%s)" % (strclass(self.__class__),
     1085                            self._testFunc.__name__)
     1086
     1087    def __repr__(self):
     1088        return "<%s testFunc=%s>" % (strclass(self.__class__),
     1089                                     self._testFunc)
     1090
     1091    def shortDescription(self):
     1092        if self._description is not None:
     1093            return self._description
     1094        doc = self._testFunc.__doc__
     1095        return doc and doc.split("\n")[0].strip() or None
  • django/utils/unittest/util.py

     
     1"""Various utility functions."""
     2
     3__unittest = True
     4
     5
     6_MAX_LENGTH = 80
     7def safe_repr(obj, short=False):
     8    try:
     9        result = repr(obj)
     10    except Exception:
     11        result = object.__repr__(obj)
     12    if not short or len(result) < _MAX_LENGTH:
     13        return result
     14    return result[:_MAX_LENGTH] + ' [truncated]...'
     15
     16def safe_str(obj):
     17    try:
     18        return str(obj)
     19    except Exception:
     20        return object.__str__(obj)
     21
     22def strclass(cls):
     23    return "%s.%s" % (cls.__module__, cls.__name__)
     24
     25def sorted_list_difference(expected, actual):
     26    """Finds elements in only one or the other of two, sorted input lists.
     27
     28    Returns a two-element tuple of lists.    The first list contains those
     29    elements in the "expected" list but not in the "actual" list, and the
     30    second contains those elements in the "actual" list but not in the
     31    "expected" list.    Duplicate elements in either input list are ignored.
     32    """
     33    i = j = 0
     34    missing = []
     35    unexpected = []
     36    while True:
     37        try:
     38            e = expected[i]
     39            a = actual[j]
     40            if e < a:
     41                missing.append(e)
     42                i += 1
     43                while expected[i] == e:
     44                    i += 1
     45            elif e > a:
     46                unexpected.append(a)
     47                j += 1
     48                while actual[j] == a:
     49                    j += 1
     50            else:
     51                i += 1
     52                try:
     53                    while expected[i] == e:
     54                        i += 1
     55                finally:
     56                    j += 1
     57                    while actual[j] == a:
     58                        j += 1
     59        except IndexError:
     60            missing.extend(expected[i:])
     61            unexpected.extend(actual[j:])
     62            break
     63    return missing, unexpected
     64
     65def unorderable_list_difference(expected, actual, ignore_duplicate=False):
     66    """Same behavior as sorted_list_difference but
     67    for lists of unorderable items (like dicts).
     68
     69    As it does a linear search per item (remove) it
     70    has O(n*n) performance.
     71    """
     72    missing = []
     73    unexpected = []
     74    while expected:
     75        item = expected.pop()
     76        try:
     77            actual.remove(item)
     78        except ValueError:
     79            missing.append(item)
     80        if ignore_duplicate:
     81            for lst in expected, actual:
     82                try:
     83                    while True:
     84                        lst.remove(item)
     85                except ValueError:
     86                    pass
     87    if ignore_duplicate:
     88        while actual:
     89            item = actual.pop()
     90            unexpected.append(item)
     91            try:
     92                while True:
     93                    actual.remove(item)
     94            except ValueError:
     95                pass
     96        return missing, unexpected
     97
     98    # anything left in actual is unexpected
     99    return missing, actual
  • django/utils/unittest/result.py

     
     1"""Test result object"""
     2
     3import sys
     4import traceback
     5import unittest
     6
     7from StringIO import StringIO
     8
     9from django.utils.unittest import util
     10from django.utils.unittest.compatibility import wraps
     11
     12__unittest = True
     13
     14def failfast(method):
     15    def inner(self, *args, **kw):
     16        if getattr(self, 'failfast', False):
     17            self.stop()
     18        return method(self, *args, **kw)
     19    inner = wraps(method)(inner)
     20    return inner
     21
     22
     23STDOUT_LINE = '\nStdout:\n%s'
     24STDERR_LINE = '\nStderr:\n%s'
     25
     26class TestResult(unittest.TestResult):
     27    """Holder for test result information.
     28
     29    Test results are automatically managed by the TestCase and TestSuite
     30    classes, and do not need to be explicitly manipulated by writers of tests.
     31
     32    Each instance holds the total number of tests run, and collections of
     33    failures and errors that occurred among those test runs. The collections
     34    contain tuples of (testcase, exceptioninfo), where exceptioninfo is the
     35    formatted traceback of the error that occurred.
     36    """
     37    _previousTestClass = None
     38    _moduleSetUpFailed = False
     39   
     40    def __init__(self):
     41        self.failfast = False
     42        self.failures = []
     43        self.errors = []
     44        self.testsRun = 0
     45        self.skipped = []
     46        self.expectedFailures = []
     47        self.unexpectedSuccesses = []
     48        self.shouldStop = False
     49        self.buffer = False
     50        self._stdout_buffer = None
     51        self._stderr_buffer = None
     52        self._original_stdout = sys.stdout
     53        self._original_stderr = sys.stderr
     54        self._mirrorOutput = False
     55   
     56    def startTest(self, test):
     57        "Called when the given test is about to be run"
     58        self.testsRun += 1
     59        self._mirrorOutput = False
     60        if self.buffer:
     61            if self._stderr_buffer is None:
     62                self._stderr_buffer = StringIO()
     63                self._stdout_buffer = StringIO()
     64            sys.stdout = self._stdout_buffer
     65            sys.stderr = self._stderr_buffer
     66
     67    def startTestRun(self):
     68        """Called once before any tests are executed.
     69
     70        See startTest for a method called before each test.
     71        """
     72
     73    def stopTest(self, test):
     74        """Called when the given test has been run"""
     75        if self.buffer:
     76            if self._mirrorOutput:
     77                output = sys.stdout.getvalue()
     78                error = sys.stderr.getvalue()
     79                if output:
     80                    if not output.endswith('\n'):
     81                        output += '\n'
     82                    self._original_stdout.write(STDOUT_LINE % output)
     83                if error:
     84                    if not error.endswith('\n'):
     85                        error += '\n'
     86                    self._original_stderr.write(STDERR_LINE % error)
     87               
     88            sys.stdout = self._original_stdout
     89            sys.stderr = self._original_stderr
     90            self._stdout_buffer.seek(0)
     91            self._stdout_buffer.truncate()
     92            self._stderr_buffer.seek(0)
     93            self._stderr_buffer.truncate()
     94        self._mirrorOutput = False
     95       
     96
     97    def stopTestRun(self):
     98        """Called once after all tests are executed.
     99
     100        See stopTest for a method called after each test.
     101        """
     102
     103
     104    def addError(self, test, err):
     105        """Called when an error has occurred. 'err' is a tuple of values as
     106        returned by sys.exc_info().
     107        """
     108        self.errors.append((test, self._exc_info_to_string(err, test)))
     109        self._mirrorOutput = True
     110    addError = failfast(addError)
     111
     112    def addFailure(self, test, err):
     113        """Called when an error has occurred. 'err' is a tuple of values as
     114        returned by sys.exc_info()."""
     115        self.failures.append((test, self._exc_info_to_string(err, test)))
     116        self._mirrorOutput = True
     117    addFailure = failfast(addFailure)
     118   
     119    def addSuccess(self, test):
     120        "Called when a test has completed successfully"
     121        pass
     122
     123    def addSkip(self, test, reason):
     124        """Called when a test is skipped."""
     125        self.skipped.append((test, reason))
     126
     127    def addExpectedFailure(self, test, err):
     128        """Called when an expected failure/error occured."""
     129        self.expectedFailures.append(
     130            (test, self._exc_info_to_string(err, test)))
     131
     132    def addUnexpectedSuccess(self, test):
     133        """Called when a test was expected to fail, but succeed."""
     134        self.unexpectedSuccesses.append(test)
     135    addUnexpectedSuccess = failfast(addUnexpectedSuccess)
     136
     137    def wasSuccessful(self):
     138        "Tells whether or not this result was a success"
     139        return (len(self.failures) + len(self.errors) == 0)
     140
     141    def stop(self):
     142        "Indicates that the tests should be aborted"
     143        self.shouldStop = True
     144
     145    def _exc_info_to_string(self, err, test):
     146        """Converts a sys.exc_info()-style tuple of values into a string."""
     147        exctype, value, tb = err
     148        # Skip test runner traceback levels
     149        while tb and self._is_relevant_tb_level(tb):
     150            tb = tb.tb_next
     151        if exctype is test.failureException:
     152            # Skip assert*() traceback levels
     153            length = self._count_relevant_tb_levels(tb)
     154            msgLines = traceback.format_exception(exctype, value, tb, length)
     155        else:
     156            msgLines = traceback.format_exception(exctype, value, tb)
     157       
     158        if self.buffer:
     159            output = sys.stdout.getvalue()
     160            error = sys.stderr.getvalue()           
     161            if output:
     162                if not output.endswith('\n'):
     163                    output += '\n'
     164                msgLines.append(STDOUT_LINE % output)
     165            if error:
     166                if not error.endswith('\n'):
     167                    error += '\n'
     168                msgLines.append(STDERR_LINE % error)
     169        return ''.join(msgLines)
     170
     171    def _is_relevant_tb_level(self, tb):
     172        return '__unittest' in tb.tb_frame.f_globals
     173
     174    def _count_relevant_tb_levels(self, tb):
     175        length = 0
     176        while tb and not self._is_relevant_tb_level(tb):
     177            length += 1
     178            tb = tb.tb_next
     179        return length
     180
     181    def __repr__(self):
     182        return "<%s run=%i errors=%i failures=%i>" % \
     183               (util.strclass(self.__class__), self.testsRun, len(self.errors),
     184                len(self.failures))
  • django/utils/unittest/__init__.py

     
     1import sys
     2
     3#Django hackery to load the appropriate version of unittest
     4
     5if sys.version_info >= (2,7):
     6    #unittest2 features are native in Python 2.7
     7    from unittest import *
     8else:
     9    try:
     10        #check the system path first
     11        from unittest2 import *
     12    except ImportError:
     13        #otherwise fall back to our bundled version
     14        from unittest2_package_init import *
  • django/utils/unittest/unittest2_package_init.py

     
     1"""
     2unittest2
     3
     4unittest2 is a backport of the new features added to the unittest testing
     5framework in Python 2.7. It is tested to run on Python 2.4 - 2.6.
     6
     7To use unittest2 instead of unittest simply replace ``import unittest`` with
     8``import unittest2``.
     9
     10
     11Copyright (c) 1999-2003 Steve Purcell
     12Copyright (c) 2003-2010 Python Software Foundation
     13This module is free software, and you may redistribute it and/or modify
     14it under the same terms as Python itself, so long as this copyright message
     15and disclaimer are retained in their original form.
     16
     17IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
     18SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
     19THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     20DAMAGE.
     21
     22THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
     23LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     24PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
     25AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
     26SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
     27"""
     28
     29__all__ = ['TestResult', 'TestCase', 'TestSuite',
     30           'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
     31           'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
     32           'expectedFailure', 'TextTestResult', '__version__', 'collector']
     33
     34__version__ = '0.5.0 alpha'
     35
     36# Expose obsolete functions for backwards compatibility
     37__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
     38
     39
     40from django.utils.unittest.collector import collector
     41from django.utils.unittest.result import TestResult
     42from django.utils.unittest.case import \
     43    TestCase, FunctionTestCase, SkipTest, skip, skipIf,\
     44    skipUnless, expectedFailure
     45
     46from django.utils.unittest.suite import BaseTestSuite, TestSuite
     47from django.utils.unittest.loader import \
     48    TestLoader, defaultTestLoader, makeSuite, getTestCaseNames,\
     49    findTestCases
     50
     51from django.utils.unittest.main import TestProgram, main, main_
     52from django.utils.unittest.runner import TextTestRunner, TextTestResult
     53
     54try:
     55    from django.utils.unittest.signals import\
     56        installHandler, registerResult, removeResult, removeHandler
     57except ImportError:
     58    # Compatibility with platforms that don't have the signal module
     59    pass
     60else:
     61    __all__.extend(['installHandler', 'registerResult', 'removeResult',
     62                    'removeHandler'])
     63
     64# deprecated
     65_TextTestResult = TextTestResult
     66
     67__unittest = True
  • django/utils/unittest/__main__.py

     
     1"""Main entry point"""
     2
     3import sys
     4if sys.argv[0].endswith("__main__.py"):
     5    sys.argv[0] = "unittest2"
     6
     7__unittest = True
     8
     9from django.utils.unittest.main import main_
     10main_()
  • django/utils/unittest/signals.py

     
     1import signal
     2import weakref
     3
     4from django.utils.unittest.compatibility import wraps
     5
     6__unittest = True
     7
     8
     9class _InterruptHandler(object):
     10    def __init__(self, default_handler):
     11        self.called = False
     12        self.default_handler = default_handler
     13
     14    def __call__(self, signum, frame):
     15        installed_handler = signal.getsignal(signal.SIGINT)
     16        if installed_handler is not self:
     17            # if we aren't the installed handler, then delegate immediately
     18            # to the default handler
     19            self.default_handler(signum, frame)
     20           
     21        if self.called:
     22            self.default_handler(signum, frame)
     23        self.called = True
     24        for result in _results.keys():
     25            result.stop()
     26
     27_results = weakref.WeakKeyDictionary()
     28def registerResult(result):
     29    _results[result] = 1
     30
     31def removeResult(result):
     32    return bool(_results.pop(result, None))
     33
     34_interrupt_handler = None
     35def installHandler():
     36    global _interrupt_handler
     37    if _interrupt_handler is None:
     38        default_handler = signal.getsignal(signal.SIGINT)
     39        _interrupt_handler = _InterruptHandler(default_handler)
     40        signal.signal(signal.SIGINT, _interrupt_handler)
     41
     42
     43def removeHandler(method=None):
     44    if method is not None:
     45        def inner(*args, **kwargs):
     46            initial = signal.getsignal(signal.SIGINT)
     47            removeHandler()
     48            try:
     49                return method(*args, **kwargs)
     50            finally:
     51                signal.signal(signal.SIGINT, initial)
     52        inner = wraps(method)(inner)
     53        return inner
     54
     55    global _interrupt_handler
     56    if _interrupt_handler is not None:
     57        signal.signal(signal.SIGINT, _interrupt_handler.default_handler)
  • django/utils/unittest/main.py

     
     1"""Unittest main program"""
     2
     3import sys
     4import os
     5import types
     6
     7from django.utils.unittest import loader, runner
     8try:
     9    from django.utils.unittest.signals import installHandler
     10except ImportError:
     11    installHandler = None
     12
     13__unittest = True
     14
     15FAILFAST     = "  -f, --failfast   Stop on first failure\n"
     16CATCHBREAK   = "  -c, --catch      Catch control-C and display results\n"
     17BUFFEROUTPUT = "  -b, --buffer     Buffer stdout and stderr during test runs\n"
     18
     19USAGE_AS_MAIN = """\
     20Usage: %(progName)s [options] [tests]
     21
     22Options:
     23  -h, --help       Show this message
     24  -v, --verbose    Verbose output
     25  -q, --quiet      Minimal output
     26%(failfast)s%(catchbreak)s%(buffer)s
     27Examples:
     28  %(progName)s test_module                       - run tests from test_module
     29  %(progName)s test_module.TestClass             - run tests from
     30                                                   test_module.TestClass
     31  %(progName)s test_module.TestClass.test_method - run specified test method
     32
     33[tests] can be a list of any number of test modules, classes and test
     34methods.
     35
     36Alternative Usage: %(progName)s discover [options]
     37
     38Options:
     39  -v, --verbose    Verbose output
     40%(failfast)s%(catchbreak)s%(buffer)s  -s directory     Directory to start discovery ('.' default)
     41  -p pattern       Pattern to match test files ('test*.py' default)
     42  -t directory     Top level directory of project (default to
     43                   start directory)
     44
     45For test discovery all test modules must be importable from the top
     46level directory of the project.
     47"""
     48
     49USAGE_FROM_MODULE = """\
     50Usage: %(progName)s [options] [test] [...]
     51
     52Options:
     53  -h, --help       Show this message
     54  -v, --verbose    Verbose output
     55  -q, --quiet      Minimal output
     56%(failfast)s%(catchbreak)s%(buffer)s
     57Examples:
     58  %(progName)s                               - run default set of tests
     59  %(progName)s MyTestSuite                   - run suite 'MyTestSuite'
     60  %(progName)s MyTestCase.testSomething      - run MyTestCase.testSomething
     61  %(progName)s MyTestCase                    - run all 'test*' test methods
     62                                               in MyTestCase
     63"""
     64
     65
     66class TestProgram(object):
     67    """A command-line program that runs a set of tests; this is primarily
     68       for making test modules conveniently executable.
     69    """
     70    USAGE = USAGE_FROM_MODULE
     71   
     72    # defaults for testing
     73    failfast = catchbreak = buffer = progName = None
     74
     75    def __init__(self, module='__main__', defaultTest=None,
     76                 argv=None, testRunner=None,
     77                 testLoader=loader.defaultTestLoader, exit=True,
     78                 verbosity=1, failfast=None, catchbreak=None, buffer=None):
     79        if isinstance(module, basestring):
     80            self.module = __import__(module)
     81            for part in module.split('.')[1:]:
     82                self.module = getattr(self.module, part)
     83        else:
     84            self.module = module
     85        if argv is None:
     86            argv = sys.argv
     87
     88        self.exit = exit
     89        self.verbosity = verbosity
     90        self.failfast = failfast
     91        self.catchbreak = catchbreak
     92        self.buffer = buffer
     93        self.defaultTest = defaultTest
     94        self.testRunner = testRunner
     95        self.testLoader = testLoader
     96        self.progName = os.path.basename(argv[0])
     97        self.parseArgs(argv)
     98        self.runTests()
     99
     100    def usageExit(self, msg=None):
     101        if msg:
     102            print msg
     103        usage = {'progName': self.progName, 'catchbreak': '', 'failfast': '',
     104                 'buffer': ''}
     105        if self.failfast != False:
     106            usage['failfast'] = FAILFAST
     107        if self.catchbreak != False and installHandler is not None:
     108            usage['catchbreak'] = CATCHBREAK
     109        if self.buffer != False:
     110            usage['buffer'] = BUFFEROUTPUT
     111        print self.USAGE % usage
     112        sys.exit(2)
     113
     114    def parseArgs(self, argv):
     115        if len(argv) > 1 and argv[1].lower() == 'discover':
     116            self._do_discovery(argv[2:])
     117            return
     118
     119        import getopt
     120        long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer']
     121        try:
     122            options, args = getopt.getopt(argv[1:], 'hHvqfcb', long_opts)
     123            for opt, value in options:
     124                if opt in ('-h','-H','--help'):
     125                    self.usageExit()
     126                if opt in ('-q','--quiet'):
     127                    self.verbosity = 0
     128                if opt in ('-v','--verbose'):
     129                    self.verbosity = 2
     130                if opt in ('-f','--failfast'):
     131                    if self.failfast is None:
     132                        self.failfast = True
     133                    # Should this raise an exception if -f is not valid?
     134                if opt in ('-c','--catch'):
     135                    if self.catchbreak is None and installHandler is not None:
     136                        self.catchbreak = True
     137                    # Should this raise an exception if -c is not valid?
     138                if opt in ('-b','--buffer'):
     139                    if self.buffer is None:
     140                        self.buffer = True
     141                    # Should this raise an exception if -b is not valid?
     142            if len(args) == 0 and self.defaultTest is None:
     143                # createTests will load tests from self.module
     144                self.testNames = None
     145            elif len(args) > 0:
     146                self.testNames = args
     147                if __name__ == '__main__':
     148                    # to support python -m unittest ...
     149                    self.module = None
     150            else:
     151                self.testNames = (self.defaultTest,)
     152            self.createTests()
     153        except getopt.error, msg:
     154            self.usageExit(msg)
     155
     156    def createTests(self):
     157        if self.testNames is None:
     158            self.test = self.testLoader.loadTestsFromModule(self.module)
     159        else:
     160            self.test = self.testLoader.loadTestsFromNames(self.testNames,
     161                                                           self.module)
     162
     163    def _do_discovery(self, argv, Loader=loader.TestLoader):
     164        # handle command line args for test discovery
     165        self.progName = '%s discover' % self.progName
     166        import optparse
     167        parser = optparse.OptionParser()
     168        parser.prog = self.progName
     169        parser.add_option('-v', '--verbose', dest='verbose', default=False,
     170                          help='Verbose output', action='store_true')
     171        if self.failfast != False:
     172            parser.add_option('-f', '--failfast', dest='failfast', default=False,
     173                              help='Stop on first fail or error',
     174                              action='store_true')
     175        if self.catchbreak != False and installHandler is not None:
     176            parser.add_option('-c', '--catch', dest='catchbreak', default=False,
     177                              help='Catch ctrl-C and display results so far',
     178                              action='store_true')
     179        if self.buffer != False:
     180            parser.add_option('-b', '--buffer', dest='buffer', default=False,
     181                              help='Buffer stdout and stderr during tests',
     182                              action='store_true')
     183        parser.add_option('-s', '--start-directory', dest='start', default='.',
     184                          help="Directory to start discovery ('.' default)")
     185        parser.add_option('-p', '--pattern', dest='pattern', default='test*.py',
     186                          help="Pattern to match tests ('test*.py' default)")
     187        parser.add_option('-t', '--top-level-directory', dest='top', default=None,
     188                          help='Top level directory of project (defaults to start directory)')
     189
     190        options, args = parser.parse_args(argv)
     191        if len(args) > 3:
     192            self.usageExit()
     193
     194        for name, value in zip(('start', 'pattern', 'top'), args):
     195            setattr(options, name, value)
     196       
     197        # only set options from the parsing here
     198        # if they weren't set explicitly in the constructor
     199        if self.failfast is None:
     200            self.failfast = options.failfast
     201        if self.catchbreak is None and installHandler is not None:
     202            self.catchbreak = options.catchbreak
     203        if self.buffer is None:
     204            self.buffer = options.buffer
     205       
     206        if options.verbose:
     207            self.verbosity = 2
     208
     209        start_dir = options.start
     210        pattern = options.pattern
     211        top_level_dir = options.top
     212
     213        loader = Loader()
     214        self.test = loader.discover(start_dir, pattern, top_level_dir)
     215
     216    def runTests(self):
     217        if self.catchbreak:
     218            installHandler()
     219        if self.testRunner is None:
     220            self.testRunner = runner.TextTestRunner
     221        if isinstance(self.testRunner, (type, types.ClassType)):
     222            try:
     223                testRunner = self.testRunner(verbosity=self.verbosity,
     224                                             failfast=self.failfast,
     225                                             buffer=self.buffer)
     226            except TypeError:
     227                # didn't accept the verbosity, buffer or failfast arguments
     228                testRunner = self.testRunner()
     229        else:
     230            # it is assumed to be a TestRunner instance
     231            testRunner = self.testRunner
     232        self.result = testRunner.run(self.test)
     233        if self.exit:
     234            sys.exit(not self.result.wasSuccessful())
     235
     236main = TestProgram
     237
     238def main_():
     239    TestProgram.USAGE = USAGE_AS_MAIN
     240    main(module=None)
     241
  • django/utils/unittest/collector.py

     
     1import os
     2import sys
     3from django.utils.unittest.loader import defaultTestLoader
     4
     5def collector():
     6    # import __main__ triggers code re-execution
     7    __main__ = sys.modules['__main__']
     8    setupDir = os.path.abspath(os.path.dirname(__main__.__file__))
     9    return defaultTestLoader.discover(setupDir)
  • django/utils/unittest/loader.py

     
     1"""Loading unittests."""
     2
     3import os
     4import re
     5import sys
     6import traceback
     7import types
     8import unittest
     9
     10from fnmatch import fnmatch
     11
     12from django.utils.unittest import case, suite
     13
     14try:
     15    from os.path import relpath
     16except ImportError:
     17    from django.utils.unittest.compatibility import relpath
     18
     19__unittest = True
     20
     21
     22def _CmpToKey(mycmp):
     23    'Convert a cmp= function into a key= function'
     24    class K(object):
     25        def __init__(self, obj):
     26            self.obj = obj
     27        def __lt__(self, other):
     28            return mycmp(self.obj, other.obj) == -1
     29    return K
     30
     31
     32# what about .pyc or .pyo (etc)
     33# we would need to avoid loading the same tests multiple times
     34# from '.py', '.pyc' *and* '.pyo'
     35VALID_MODULE_NAME = re.compile(r'[_a-z]\w*\.py$', re.IGNORECASE)
     36
     37
     38def _make_failed_import_test(name, suiteClass):
     39    message = 'Failed to import test module: %s' % name
     40    if hasattr(traceback, 'format_exc'):
     41        # Python 2.3 compatibility
     42        # format_exc returns two frames of discover.py as well
     43        message += '\n%s' % traceback.format_exc()
     44    return _make_failed_test('ModuleImportFailure', name, ImportError(message),
     45                             suiteClass)
     46
     47def _make_failed_load_tests(name, exception, suiteClass):
     48    return _make_failed_test('LoadTestsFailure', name, exception, suiteClass)
     49
     50def _make_failed_test(classname, methodname, exception, suiteClass):
     51    def testFailure(self):
     52        raise exception
     53    attrs = {methodname: testFailure}
     54    TestClass = type(classname, (case.TestCase,), attrs)
     55    return suiteClass((TestClass(methodname),))
     56   
     57
     58class TestLoader(unittest.TestLoader):
     59    """
     60    This class is responsible for loading tests according to various criteria
     61    and returning them wrapped in a TestSuite
     62    """
     63    testMethodPrefix = 'test'
     64    sortTestMethodsUsing = cmp
     65    suiteClass = suite.TestSuite
     66    _top_level_dir = None
     67
     68    def loadTestsFromTestCase(self, testCaseClass):
     69        """Return a suite of all tests cases contained in testCaseClass"""
     70        if issubclass(testCaseClass, suite.TestSuite):
     71            raise TypeError("Test cases should not be derived from TestSuite."
     72                            " Maybe you meant to derive from TestCase?")
     73        testCaseNames = self.getTestCaseNames(testCaseClass)
     74        if not testCaseNames and hasattr(testCaseClass, 'runTest'):
     75            testCaseNames = ['runTest']
     76        loaded_suite = self.suiteClass(map(testCaseClass, testCaseNames))
     77        return loaded_suite
     78
     79    def loadTestsFromModule(self, module, use_load_tests=True):
     80        """Return a suite of all tests cases contained in the given module"""
     81        tests = []
     82        for name in dir(module):
     83            obj = getattr(module, name)
     84            if isinstance(obj, type) and issubclass(obj, unittest.TestCase):
     85                tests.append(self.loadTestsFromTestCase(obj))
     86
     87        load_tests = getattr(module, 'load_tests', None)
     88        tests = self.suiteClass(tests)
     89        if use_load_tests and load_tests is not None:
     90            try:
     91                return load_tests(self, tests, None)
     92            except Exception, e:
     93                return _make_failed_load_tests(module.__name__, e,
     94                                               self.suiteClass)
     95        return tests
     96
     97    def loadTestsFromName(self, name, module=None):
     98        """Return a suite of all tests cases given a string specifier.
     99
     100        The name may resolve either to a module, a test case class, a
     101        test method within a test case class, or a callable object which
     102        returns a TestCase or TestSuite instance.
     103
     104        The method optionally resolves the names relative to a given module.
     105        """
     106        parts = name.split('.')
     107        if module is None:
     108            parts_copy = parts[:]
     109            while parts_copy:
     110                try:
     111                    module = __import__('.'.join(parts_copy))
     112                    break
     113                except ImportError:
     114                    del parts_copy[-1]
     115                    if not parts_copy:
     116                        raise
     117            parts = parts[1:]
     118        obj = module
     119        for part in parts:
     120            parent, obj = obj, getattr(obj, part)
     121
     122        if isinstance(obj, types.ModuleType):
     123            return self.loadTestsFromModule(obj)
     124        elif isinstance(obj, type) and issubclass(obj, unittest.TestCase):
     125            return self.loadTestsFromTestCase(obj)
     126        elif (isinstance(obj, types.UnboundMethodType) and
     127              isinstance(parent, type) and
     128              issubclass(parent, case.TestCase)):
     129            return self.suiteClass([parent(obj.__name__)])
     130        elif isinstance(obj, unittest.TestSuite):
     131            return obj
     132        elif hasattr(obj, '__call__'):
     133            test = obj()
     134            if isinstance(test, unittest.TestSuite):
     135                return test
     136            elif isinstance(test, unittest.TestCase):
     137                return self.suiteClass([test])
     138            else:
     139                raise TypeError("calling %s returned %s, not a test" %
     140                                (obj, test))
     141        else:
     142            raise TypeError("don't know how to make test from: %s" % obj)
     143
     144    def loadTestsFromNames(self, names, module=None):
     145        """Return a suite of all tests cases found using the given sequence
     146        of string specifiers. See 'loadTestsFromName()'.
     147        """
     148        suites = [self.loadTestsFromName(name, module) for name in names]
     149        return self.suiteClass(suites)
     150
     151    def getTestCaseNames(self, testCaseClass):
     152        """Return a sorted sequence of method names found within testCaseClass
     153        """
     154        def isTestMethod(attrname, testCaseClass=testCaseClass,
     155                         prefix=self.testMethodPrefix):
     156            return attrname.startswith(prefix) and \
     157                hasattr(getattr(testCaseClass, attrname), '__call__')
     158        testFnNames = filter(isTestMethod, dir(testCaseClass))
     159        if self.sortTestMethodsUsing:
     160            # testFnNames.sort(key=_CmpToKey(self.sortTestMethodsUsing))
     161            testFnNames.sort(self.sortTestMethodsUsing)
     162        return testFnNames
     163
     164    def discover(self, start_dir, pattern='test*.py', top_level_dir=None):
     165        """Find and return all test modules from the specified start
     166        directory, recursing into subdirectories to find them. Only test files
     167        that match the pattern will be loaded. (Using shell style pattern
     168        matching.)
     169
     170        All test modules must be importable from the top level of the project.
     171        If the start directory is not the top level directory then the top
     172        level directory must be specified separately.
     173
     174        If a test package name (directory with '__init__.py') matches the
     175        pattern then the package will be checked for a 'load_tests' function. If
     176        this exists then it will be called with loader, tests, pattern.
     177
     178        If load_tests exists then discovery does  *not* recurse into the package,
     179        load_tests is responsible for loading all tests in the package.
     180
     181        The pattern is deliberately not stored as a loader attribute so that
     182        packages can continue discovery themselves. top_level_dir is stored so
     183        load_tests does not need to pass this argument in to loader.discover().
     184        """
     185        set_implicit_top = False
     186        if top_level_dir is None and self._top_level_dir is not None:
     187            # make top_level_dir optional if called from load_tests in a package
     188            top_level_dir = self._top_level_dir
     189        elif top_level_dir is None:
     190            set_implicit_top = True
     191            top_level_dir = start_dir
     192
     193        top_level_dir = os.path.abspath(top_level_dir)
     194
     195        if not top_level_dir in sys.path:
     196            # all test modules must be importable from the top level directory
     197            # should we *unconditionally* put the start directory in first
     198            # in sys.path to minimise likelihood of conflicts between installed
     199            # modules and development versions?
     200            sys.path.insert(0, top_level_dir)
     201        self._top_level_dir = top_level_dir
     202
     203        is_not_importable = False
     204        if os.path.isdir(os.path.abspath(start_dir)):
     205            start_dir = os.path.abspath(start_dir)
     206            if start_dir != top_level_dir:
     207                is_not_importable = not os.path.isfile(os.path.join(start_dir, '__init__.py'))
     208        else:
     209            # support for discovery from dotted module names
     210            try:
     211                __import__(start_dir)
     212            except ImportError:
     213                is_not_importable = True
     214            else:
     215                the_module = sys.modules[start_dir]
     216                top_part = start_dir.split('.')[0]
     217                start_dir = os.path.abspath(os.path.dirname((the_module.__file__)))
     218                if set_implicit_top:
     219                    self._top_level_dir = os.path.abspath(os.path.dirname(os.path.dirname(sys.modules[top_part].__file__)))
     220                    sys.path.remove(top_level_dir)
     221
     222        if is_not_importable:
     223            raise ImportError('Start directory is not importable: %r' % start_dir)
     224
     225        tests = list(self._find_tests(start_dir, pattern))
     226        return self.suiteClass(tests)
     227
     228    def _get_name_from_path(self, path):
     229        path = os.path.splitext(os.path.normpath(path))[0]
     230
     231        _relpath = relpath(path, self._top_level_dir)
     232        assert not os.path.isabs(_relpath), "Path must be within the project"
     233        assert not _relpath.startswith('..'), "Path must be within the project"
     234
     235        name = _relpath.replace(os.path.sep, '.')
     236        return name
     237
     238    def _get_module_from_name(self, name):
     239        __import__(name)
     240        return sys.modules[name]
     241
     242    def _match_path(self, path, full_path, pattern):
     243        # override this method to use alternative matching strategy
     244        return fnmatch(path, pattern)
     245   
     246    def _find_tests(self, start_dir, pattern):
     247        """Used by discovery. Yields test suites it loads."""
     248        paths = os.listdir(start_dir)
     249
     250        for path in paths:
     251            full_path = os.path.join(start_dir, path)
     252            if os.path.isfile(full_path):
     253                if not VALID_MODULE_NAME.match(path):
     254                    # valid Python identifiers only
     255                    continue
     256                if not self._match_path(path, full_path, pattern):
     257                    continue
     258                # if the test file matches, load it
     259                name = self._get_name_from_path(full_path)
     260                try:
     261                    module = self._get_module_from_name(name)
     262                except:
     263                    yield _make_failed_import_test(name, self.suiteClass)
     264                else:
     265                    mod_file = os.path.abspath(getattr(module, '__file__', full_path))
     266                    realpath = os.path.splitext(mod_file)[0]
     267                    fullpath_noext = os.path.splitext(full_path)[0]
     268                    if realpath.lower() != fullpath_noext.lower():
     269                        module_dir = os.path.dirname(realpath)
     270                        mod_name = os.path.splitext(os.path.basename(full_path))[0]
     271                        expected_dir = os.path.dirname(full_path)
     272                        msg = ("%r module incorrectly imported from %r. Expected %r. "
     273                               "Is this module globally installed?")
     274                        raise ImportError(msg % (mod_name, module_dir, expected_dir))
     275                    yield self.loadTestsFromModule(module)
     276            elif os.path.isdir(full_path):
     277                if not os.path.isfile(os.path.join(full_path, '__init__.py')):
     278                    continue
     279
     280                load_tests = None
     281                tests = None
     282                if fnmatch(path, pattern):
     283                    # only check load_tests if the package directory itself matches the filter
     284                    name = self._get_name_from_path(full_path)
     285                    package = self._get_module_from_name(name)
     286                    load_tests = getattr(package, 'load_tests', None)
     287                    tests = self.loadTestsFromModule(package, use_load_tests=False)
     288
     289                if load_tests is None:
     290                    if tests is not None:
     291                        # tests loaded from package file
     292                        yield tests
     293                    # recurse into the package
     294                    for test in self._find_tests(full_path, pattern):
     295                        yield test
     296                else:
     297                    try:
     298                        yield load_tests(self, tests, pattern)
     299                    except Exception, e:
     300                        yield _make_failed_load_tests(package.__name__, e,
     301                                                      self.suiteClass)
     302
     303defaultTestLoader = TestLoader()
     304
     305
     306def _makeLoader(prefix, sortUsing, suiteClass=None):
     307    loader = TestLoader()
     308    loader.sortTestMethodsUsing = sortUsing
     309    loader.testMethodPrefix = prefix
     310    if suiteClass:
     311        loader.suiteClass = suiteClass
     312    return loader
     313
     314def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
     315    return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
     316
     317def makeSuite(testCaseClass, prefix='test', sortUsing=cmp,
     318              suiteClass=suite.TestSuite):
     319    return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
     320
     321def findTestCases(module, prefix='test', sortUsing=cmp,
     322                  suiteClass=suite.TestSuite):
     323    return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
  • tests/regressiontests/test_client_regress/models.py

     
    3434        try:
    3535            self.assertContains(response, 'text', status_code=999)
    3636        except AssertionError, e:
    37             self.assertEquals(str(e), "Couldn't retrieve content: Response code was 200 (expected 999)")
     37            self.assertTrue("Couldn't retrieve content: Response code was 200 (expected 999)" in str(e))
    3838        try:
    3939            self.assertContains(response, 'text', status_code=999, msg_prefix='abc')
    4040        except AssertionError, e:
    41             self.assertEquals(str(e), "abc: Couldn't retrieve content: Response code was 200 (expected 999)")
     41            self.assertTrue("abc: Couldn't retrieve content: Response code was 200 (expected 999)" in str(e))
    4242
    4343        try:
    4444            self.assertNotContains(response, 'text', status_code=999)
    4545        except AssertionError, e:
    46             self.assertEquals(str(e), "Couldn't retrieve content: Response code was 200 (expected 999)")
     46            self.assertTrue("Couldn't retrieve content: Response code was 200 (expected 999)" in str(e))
    4747        try:
    4848            self.assertNotContains(response, 'text', status_code=999, msg_prefix='abc')
    4949        except AssertionError, e:
    50             self.assertEquals(str(e), "abc: Couldn't retrieve content: Response code was 200 (expected 999)")
     50            self.assertTrue("abc: Couldn't retrieve content: Response code was 200 (expected 999)" in str(e))
    5151
    5252        try:
    5353            self.assertNotContains(response, 'once')
    5454        except AssertionError, e:
    55             self.assertEquals(str(e), "Response should not contain 'once'")
     55            self.assertTrue("Response should not contain 'once'" in str(e))
    5656        try:
    5757            self.assertNotContains(response, 'once', msg_prefix='abc')
    5858        except AssertionError, e:
    59             self.assertEquals(str(e), "abc: Response should not contain 'once'")
     59            self.assertTrue("abc: Response should not contain 'once'" in str(e))
    6060
    6161        try:
    6262            self.assertContains(response, 'never', 1)
    6363        except AssertionError, e:
    64             self.assertEquals(str(e), "Found 0 instances of 'never' in response (expected 1)")
     64            self.assertTrue("Found 0 instances of 'never' in response (expected 1)" in str(e))
    6565        try:
    6666            self.assertContains(response, 'never', 1, msg_prefix='abc')
    6767        except AssertionError, e:
    68             self.assertEquals(str(e), "abc: Found 0 instances of 'never' in response (expected 1)")
     68            self.assertTrue("abc: Found 0 instances of 'never' in response (expected 1)" in str(e))
    6969
    7070        try:
    7171            self.assertContains(response, 'once', 0)
    7272        except AssertionError, e:
    73             self.assertEquals(str(e), "Found 1 instances of 'once' in response (expected 0)")
     73            self.assertTrue("Found 1 instances of 'once' in response (expected 0)" in str(e))
    7474        try:
    7575            self.assertContains(response, 'once', 0, msg_prefix='abc')
    7676        except AssertionError, e:
    77             self.assertEquals(str(e), "abc: Found 1 instances of 'once' in response (expected 0)")
     77            self.assertTrue("abc: Found 1 instances of 'once' in response (expected 0)" in str(e))
    7878
    7979        try:
    8080            self.assertContains(response, 'once', 2)
    8181        except AssertionError, e:
    82             self.assertEquals(str(e), "Found 1 instances of 'once' in response (expected 2)")
     82            self.assertTrue("Found 1 instances of 'once' in response (expected 2)" in str(e))
    8383        try:
    8484            self.assertContains(response, 'once', 2, msg_prefix='abc')
    8585        except AssertionError, e:
    86             self.assertEquals(str(e), "abc: Found 1 instances of 'once' in response (expected 2)")
     86            self.assertTrue("abc: Found 1 instances of 'once' in response (expected 2)" in str(e))
    8787
    8888        try:
    8989            self.assertContains(response, 'twice', 1)
    9090        except AssertionError, e:
    91             self.assertEquals(str(e), "Found 2 instances of 'twice' in response (expected 1)")
     91            self.assertTrue("Found 2 instances of 'twice' in response (expected 1)" in str(e))
    9292        try:
    9393            self.assertContains(response, 'twice', 1, msg_prefix='abc')
    9494        except AssertionError, e:
    95             self.assertEquals(str(e), "abc: Found 2 instances of 'twice' in response (expected 1)")
     95            self.assertTrue("abc: Found 2 instances of 'twice' in response (expected 1)" in str(e))
    9696
    9797        try:
    9898            self.assertContains(response, 'thrice')
    9999        except AssertionError, e:
    100             self.assertEquals(str(e), "Couldn't find 'thrice' in response")
     100            self.assertTrue("Couldn't find 'thrice' in response" in str(e))
    101101        try:
    102102            self.assertContains(response, 'thrice', msg_prefix='abc')
    103103        except AssertionError, e:
    104             self.assertEquals(str(e), "abc: Couldn't find 'thrice' in response")
     104            self.assertTrue("abc: Couldn't find 'thrice' in response" in str(e))
    105105
    106106        try:
    107107            self.assertContains(response, 'thrice', 3)
    108108        except AssertionError, e:
    109             self.assertEquals(str(e), "Found 0 instances of 'thrice' in response (expected 3)")
     109            self.assertTrue("Found 0 instances of 'thrice' in response (expected 3)" in str(e))
    110110        try:
    111111            self.assertContains(response, 'thrice', 3, msg_prefix='abc')
    112112        except AssertionError, e:
    113             self.assertEquals(str(e), "abc: Found 0 instances of 'thrice' in response (expected 3)")
     113            self.assertTrue("abc: Found 0 instances of 'thrice' in response (expected 3)" in str(e))
    114114
    115115    def test_unicode_contains(self):
    116116        "Unicode characters can be found in template context"
     
    140140        try:
    141141            self.assertTemplateUsed(response, 'GET Template')
    142142        except AssertionError, e:
    143             self.assertEquals(str(e), "No templates used to render the response")
     143            self.assertTrue("No templates used to render the response" in str(e))
    144144
    145145        try:
    146146            self.assertTemplateUsed(response, 'GET Template', msg_prefix='abc')
    147147        except AssertionError, e:
    148             self.assertEquals(str(e), "abc: No templates used to render the response")
     148            self.assertTrue("abc: No templates used to render the response" in str(e))
    149149
    150150    def test_single_context(self):
    151151        "Template assertions work when there is a single context"
     
    154154        try:
    155155            self.assertTemplateNotUsed(response, 'Empty GET Template')
    156156        except AssertionError, e:
    157             self.assertEquals(str(e), "Template 'Empty GET Template' was used unexpectedly in rendering the response")
     157            self.assertTrue("Template 'Empty GET Template' was used unexpectedly in rendering the response" in str(e))
    158158
    159159        try:
    160160            self.assertTemplateNotUsed(response, 'Empty GET Template', msg_prefix='abc')
    161161        except AssertionError, e:
    162             self.assertEquals(str(e), "abc: Template 'Empty GET Template' was used unexpectedly in rendering the response")
     162            self.assertTrue("abc: Template 'Empty GET Template' was used unexpectedly in rendering the response" in str(e))
    163163
    164164        try:
    165165            self.assertTemplateUsed(response, 'Empty POST Template')
    166166        except AssertionError, e:
    167             self.assertEquals(str(e), "Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template")
     167            self.assertTrue("Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template" in str(e))
    168168
    169169        try:
    170170            self.assertTemplateUsed(response, 'Empty POST Template', msg_prefix='abc')
    171171        except AssertionError, e:
    172             self.assertEquals(str(e), "abc: Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template")
     172            self.assertTrue("abc: Template 'Empty POST Template' was not a template used to render the response. Actual template(s) used: Empty GET Template" in str(e))
    173173
    174174    def test_multiple_context(self):
    175175        "Template assertions work when there are multiple contexts"
     
    185185        try:
    186186            self.assertTemplateNotUsed(response, "form_view.html")
    187187        except AssertionError, e:
    188             self.assertEquals(str(e), "Template 'form_view.html' was used unexpectedly in rendering the response")
     188            self.assertTrue("Template 'form_view.html' was used unexpectedly in rendering the response" in str(e))
    189189
    190190        try:
    191191            self.assertTemplateNotUsed(response, 'base.html')
    192192        except AssertionError, e:
    193             self.assertEquals(str(e), "Template 'base.html' was used unexpectedly in rendering the response")
     193            self.assertTrue("Template 'base.html' was used unexpectedly in rendering the response" in str(e))
    194194
    195195        try:
    196196            self.assertTemplateUsed(response, "Valid POST Template")
    197197        except AssertionError, e:
    198             self.assertEquals(str(e), "Template 'Valid POST Template' was not a template used to render the response. Actual template(s) used: form_view.html, base.html")
     198            self.assertTrue("Template 'Valid POST Template' was not a template used to render the response. Actual template(s) used: form_view.html, base.html" in str(e))
    199199
    200200class AssertRedirectsTests(TestCase):
    201201    def test_redirect_page(self):
     
    205205        try:
    206206            self.assertRedirects(response, '/test_client/get_view/')
    207207        except AssertionError, e:
    208             self.assertEquals(str(e), "Response didn't redirect as expected: Response code was 301 (expected 302)")
     208            self.assertTrue("Response didn't redirect as expected: Response code was 301 (expected 302)" in str(e))
    209209
    210210        try:
    211211            self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
    212212        except AssertionError, e:
    213             self.assertEquals(str(e), "abc: Response didn't redirect as expected: Response code was 301 (expected 302)")
     213            self.assertTrue("abc: Response didn't redirect as expected: Response code was 301 (expected 302)" in str(e))
    214214
    215215    def test_lost_query(self):
    216216        "An assertion is raised if the redirect location doesn't preserve GET parameters"
     
    218218        try:
    219219            self.assertRedirects(response, '/test_client/get_view/')
    220220        except AssertionError, e:
    221             self.assertEquals(str(e), "Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'")
     221            self.assertTrue("Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'" in str(e))
    222222
    223223        try:
    224224            self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
    225225        except AssertionError, e:
    226             self.assertEquals(str(e), "abc: Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'")
     226            self.assertTrue("abc: Response redirected to 'http://testserver/test_client/get_view/?var=value', expected 'http://testserver/test_client/get_view/'" in str(e))
    227227
    228228    def test_incorrect_target(self):
    229229        "An assertion is raised if the response redirects to another target"
     
    232232            # Should redirect to get_view
    233233            self.assertRedirects(response, '/test_client/some_view/')
    234234        except AssertionError, e:
    235             self.assertEquals(str(e), "Response didn't redirect as expected: Response code was 301 (expected 302)")
     235            self.assertTrue("Response didn't redirect as expected: Response code was 301 (expected 302)" in str(e))
    236236
    237237    def test_target_page(self):
    238238        "An assertion is raised if the response redirect target cannot be retrieved as expected"
     
    241241            # The redirect target responds with a 301 code, not 200
    242242            self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/')
    243243        except AssertionError, e:
    244             self.assertEquals(str(e), "Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)")
     244            self.assertTrue("Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)" in str(e))
    245245
    246246        try:
    247247            # The redirect target responds with a 301 code, not 200
    248248            self.assertRedirects(response, 'http://testserver/test_client/permanent_redirect_view/', msg_prefix='abc')
    249249        except AssertionError, e:
    250             self.assertEquals(str(e), "abc: Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)")
     250            self.assertTrue("abc: Couldn't retrieve redirection page '/test_client/permanent_redirect_view/': response code was 301 (expected 200)" in str(e))
    251251
    252252    def test_redirect_chain(self):
    253253        "You can follow a redirect chain of multiple redirects"
     
    338338        try:
    339339            self.assertRedirects(response, '/test_client/get_view/')
    340340        except AssertionError, e:
    341             self.assertEquals(str(e), "Response didn't redirect as expected: Response code was 200 (expected 302)")
     341            self.assertTrue("Response didn't redirect as expected: Response code was 200 (expected 302)" in str(e))
    342342
    343343        try:
    344344            self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
    345345        except AssertionError, e:
    346             self.assertEquals(str(e), "abc: Response didn't redirect as expected: Response code was 200 (expected 302)")
     346            self.assertTrue("abc: Response didn't redirect as expected: Response code was 200 (expected 302)" in str(e))
    347347
    348348    def test_redirect_on_non_redirect_page(self):
    349349        "An assertion is raised if the original page couldn't be retrieved as expected"
     
    352352        try:
    353353            self.assertRedirects(response, '/test_client/get_view/')
    354354        except AssertionError, e:
    355             self.assertEquals(str(e), "Response didn't redirect as expected: Response code was 200 (expected 302)")
     355            self.assertTrue("Response didn't redirect as expected: Response code was 200 (expected 302)" in str(e))
    356356
    357357        try:
    358358            self.assertRedirects(response, '/test_client/get_view/', msg_prefix='abc')
    359359        except AssertionError, e:
    360             self.assertEquals(str(e), "abc: Response didn't redirect as expected: Response code was 200 (expected 302)")
     360            self.assertTrue("abc: Response didn't redirect as expected: Response code was 200 (expected 302)" in str(e))
    361361
    362362
    363363class AssertFormErrorTests(TestCase):
     
    377377        try:
    378378            self.assertFormError(response, 'wrong_form', 'some_field', 'Some error.')
    379379        except AssertionError, e:
    380             self.assertEqual(str(e), "The form 'wrong_form' was not used to render the response")
     380            self.assertTrue("The form 'wrong_form' was not used to render the response" in str(e))
    381381        try:
    382382            self.assertFormError(response, 'wrong_form', 'some_field', 'Some error.', msg_prefix='abc')
    383383        except AssertionError, e:
    384             self.assertEqual(str(e), "abc: The form 'wrong_form' was not used to render the response")
     384            self.assertTrue("abc: The form 'wrong_form' was not used to render the response" in str(e))
    385385
    386386    def test_unknown_field(self):
    387387        "An assertion is raised if the field name is unknown"
     
    399399        try:
    400400            self.assertFormError(response, 'form', 'some_field', 'Some error.')
    401401        except AssertionError, e:
    402             self.assertEqual(str(e), "The form 'form' in context 0 does not contain the field 'some_field'")
     402            self.assertTrue("The form 'form' in context 0 does not contain the field 'some_field'" in str(e))
    403403        try:
    404404            self.assertFormError(response, 'form', 'some_field', 'Some error.', msg_prefix='abc')
    405405        except AssertionError, e:
    406             self.assertEqual(str(e), "abc: The form 'form' in context 0 does not contain the field 'some_field'")
     406            self.assertTrue("abc: The form 'form' in context 0 does not contain the field 'some_field'" in str(e))
    407407
    408408    def test_noerror_field(self):
    409409        "An assertion is raised if the field doesn't have any errors"
     
    421421        try:
    422422            self.assertFormError(response, 'form', 'value', 'Some error.')
    423423        except AssertionError, e:
    424             self.assertEqual(str(e), "The field 'value' on form 'form' in context 0 contains no errors")
     424            self.assertTrue("The field 'value' on form 'form' in context 0 contains no errors" in str(e))
    425425        try:
    426426            self.assertFormError(response, 'form', 'value', 'Some error.', msg_prefix='abc')
    427427        except AssertionError, e:
    428             self.assertEqual(str(e), "abc: The field 'value' on form 'form' in context 0 contains no errors")
     428            self.assertTrue("abc: The field 'value' on form 'form' in context 0 contains no errors" in str(e))
    429429
    430430    def test_unknown_error(self):
    431431        "An assertion is raised if the field doesn't contain the provided error"
     
    443443        try:
    444444            self.assertFormError(response, 'form', 'email', 'Some error.')
    445445        except AssertionError, e:
    446             self.assertEqual(str(e), "The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])")
     446            self.assertTrue("The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])" in str(e))
    447447        try:
    448448            self.assertFormError(response, 'form', 'email', 'Some error.', msg_prefix='abc')
    449449        except AssertionError, e:
    450             self.assertEqual(str(e), "abc: The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])")
     450            self.assertTrue("abc: The field 'email' on form 'form' in context 0 does not contain the error 'Some error.' (actual errors: [u'Enter a valid e-mail address.'])" in str(e))
    451451
    452452    def test_unknown_nonfield_error(self):
    453453        """
     
    468468        try:
    469469            self.assertFormError(response, 'form', None, 'Some error.')
    470470        except AssertionError, e:
    471             self.assertEqual(str(e), "The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )")
     471            self.assertTrue("The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )" in str(e))
    472472        try:
    473473            self.assertFormError(response, 'form', None, 'Some error.', msg_prefix='abc')
    474474        except AssertionError, e:
    475             self.assertEqual(str(e), "abc: The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )")
     475            self.assertTrue("abc: The form 'form' in context 0 does not contain the non-field error 'Some error.' (actual errors: )" in str(e))
    476476
    477477class LoginTests(TestCase):
    478478    fixtures = ['testdata']
Back to Top