summaryrefslogtreecommitdiff
path: root/lib/subunit/python/testtools/testcase.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/subunit/python/testtools/testcase.py')
-rw-r--r--lib/subunit/python/testtools/testcase.py468
1 files changed, 0 insertions, 468 deletions
diff --git a/lib/subunit/python/testtools/testcase.py b/lib/subunit/python/testtools/testcase.py
deleted file mode 100644
index fd70141e6d..0000000000
--- a/lib/subunit/python/testtools/testcase.py
+++ /dev/null
@@ -1,468 +0,0 @@
-# Copyright (c) 2008, 2009 Jonathan M. Lange. See LICENSE for details.
-
-"""Test case related stuff."""
-
-__metaclass__ = type
-__all__ = [
- 'clone_test_with_new_id',
- 'TestCase',
- 'skip',
- 'skipIf',
- 'skipUnless',
- ]
-
-import copy
-try:
- from functools import wraps
-except ImportError:
- wraps = None
-import itertools
-import sys
-import types
-import unittest
-
-from testtools import content
-from testtools.runtest import RunTest
-from testtools.testresult import TestResult
-from testtools.utils import advance_iterator
-
-
-try:
- # Try to use the python2.7 SkipTest exception for signalling skips.
- from unittest.case import SkipTest as TestSkipped
-except ImportError:
- class TestSkipped(Exception):
- """Raised within TestCase.run() when a test is skipped."""
-
-
-try:
- # Try to use the same exceptions python 2.7 does.
- from unittest.case import _ExpectedFailure, _UnexpectedSuccess
-except ImportError:
- # Oops, not available, make our own.
- class _UnexpectedSuccess(Exception):
- """An unexpected success was raised.
-
- Note that this exception is private plumbing in testtools' testcase
- module.
- """
-
- class _ExpectedFailure(Exception):
- """An expected failure occured.
-
- Note that this exception is private plumbing in testtools' testcase
- module.
- """
-
-
-class TestCase(unittest.TestCase):
- """Extensions to the basic TestCase.
-
- :ivar exception_handlers: Exceptions to catch from setUp, runTest and
- tearDown. This list is able to be modified at any time and consists of
- (exception_class, handler(case, result, exception_value)) pairs.
- """
-
- skipException = TestSkipped
-
- def __init__(self, *args, **kwargs):
- """Construct a TestCase.
-
- :param testMethod: The name of the method to run.
- :param runTest: Optional class to use to execute the test. If not
- supplied testtools.runtest.RunTest is used. The instance to be
- used is created when run() is invoked, so will be fresh each time.
- """
- unittest.TestCase.__init__(self, *args, **kwargs)
- self._cleanups = []
- self._unique_id_gen = itertools.count(1)
- self.__setup_called = False
- self.__teardown_called = False
- self.__details = {}
- self.__RunTest = kwargs.get('runTest', RunTest)
- self.__exception_handlers = []
- self.exception_handlers = [
- (self.skipException, self._report_skip),
- (self.failureException, self._report_failure),
- (_ExpectedFailure, self._report_expected_failure),
- (_UnexpectedSuccess, self._report_unexpected_success),
- (Exception, self._report_error),
- ]
-
- def __eq__(self, other):
- eq = getattr(unittest.TestCase, '__eq__', None)
- if eq is not None and not unittest.TestCase.__eq__(self, other):
- return False
- return self.__dict__ == other.__dict__
-
- def __repr__(self):
- # We add id to the repr because it makes testing testtools easier.
- return "<%s id=0x%0x>" % (self.id(), id(self))
-
- def addDetail(self, name, content_object):
- """Add a detail to be reported with this test's outcome.
-
- For more details see pydoc testtools.TestResult.
-
- :param name: The name to give this detail.
- :param content_object: The content object for this detail. See
- testtools.content for more detail.
- """
- self.__details[name] = content_object
-
- def getDetails(self):
- """Get the details dict that will be reported with this test's outcome.
-
- For more details see pydoc testtools.TestResult.
- """
- return self.__details
-
- def shortDescription(self):
- return self.id()
-
- def skip(self, reason):
- """Cause this test to be skipped.
-
- This raises self.skipException(reason). skipException is raised
- to permit a skip to be triggered at any point (during setUp or the
- testMethod itself). The run() method catches skipException and
- translates that into a call to the result objects addSkip method.
-
- :param reason: The reason why the test is being skipped. This must
- support being cast into a unicode string for reporting.
- """
- raise self.skipException(reason)
-
- def _formatTypes(self, classOrIterable):
- """Format a class or a bunch of classes for display in an error."""
- className = getattr(classOrIterable, '__name__', None)
- if className is None:
- className = ', '.join(klass.__name__ for klass in classOrIterable)
- return className
-
- def _runCleanups(self, result):
- """Run the cleanups that have been added with addCleanup.
-
- See the docstring for addCleanup for more information.
-
- Returns True if all cleanups ran without error, False otherwise.
- """
- ok = True
- while self._cleanups:
- function, arguments, keywordArguments = self._cleanups.pop()
- try:
- function(*arguments, **keywordArguments)
- except KeyboardInterrupt:
- raise
- except:
- self._report_error(self, result, None)
- ok = False
- return ok
-
- def addCleanup(self, function, *arguments, **keywordArguments):
- """Add a cleanup function to be called after tearDown.
-
- Functions added with addCleanup will be called in reverse order of
- adding after the test method and before tearDown.
-
- If a function added with addCleanup raises an exception, the error
- will be recorded as a test error, and the next cleanup will then be
- run.
-
- Cleanup functions are always called before a test finishes running,
- even if setUp is aborted by an exception.
- """
- self._cleanups.append((function, arguments, keywordArguments))
-
- def addOnException(self, handler):
- """Add a handler to be called when an exception occurs in test code.
-
- This handler cannot affect what result methods are called, and is
- called before any outcome is called on the result object. An example
- use for it is to add some diagnostic state to the test details dict
- which is expensive to calculate and not interesting for reporting in
- the success case.
-
- Handlers are called before the outcome (such as addFailure) that
- the exception has caused.
-
- Handlers are called in first-added, first-called order, and if they
- raise an exception, that will propogate out of the test running
- machinery, halting test processing. As a result, do not call code that
- may unreasonably fail.
- """
- self.__exception_handlers.append(handler)
-
- def _add_reason(self, reason):
- self.addDetail('reason', content.Content(
- content.ContentType('text', 'plain'),
- lambda: [reason.encode('utf8')]))
-
- def assertIn(self, needle, haystack):
- """Assert that needle is in haystack."""
- self.assertTrue(
- needle in haystack, '%r not in %r' % (needle, haystack))
-
- def assertIs(self, expected, observed, message=''):
- """Assert that 'expected' is 'observed'.
-
- :param expected: The expected value.
- :param observed: The observed value.
- :param message: An optional message describing the error.
- """
- if message:
- message = ': ' + message
- self.assertTrue(
- expected is observed,
- '%r is not %r%s' % (expected, observed, message))
-
- def assertIsNot(self, expected, observed, message=''):
- """Assert that 'expected' is not 'observed'."""
- if message:
- message = ': ' + message
- self.assertTrue(
- expected is not observed,
- '%r is %r%s' % (expected, observed, message))
-
- def assertNotIn(self, needle, haystack):
- """Assert that needle is not in haystack."""
- self.assertTrue(
- needle not in haystack, '%r in %r' % (needle, haystack))
-
- def assertIsInstance(self, obj, klass):
- self.assertTrue(
- isinstance(obj, klass),
- '%r is not an instance of %s' % (obj, self._formatTypes(klass)))
-
- def assertRaises(self, excClass, callableObj, *args, **kwargs):
- """Fail unless an exception of class excClass is thrown
- by callableObj when invoked with arguments args and keyword
- arguments kwargs. If a different type of exception is
- thrown, it will not be caught, and the test case will be
- deemed to have suffered an error, exactly as for an
- unexpected exception.
- """
- try:
- ret = callableObj(*args, **kwargs)
- except excClass:
- return sys.exc_info()[1]
- else:
- excName = self._formatTypes(excClass)
- self.fail("%s not raised, %r returned instead." % (excName, ret))
- failUnlessRaises = assertRaises
-
- def assertThat(self, matchee, matcher):
- """Assert that matchee is matched by matcher.
-
- :param matchee: An object to match with matcher.
- :param matcher: An object meeting the testtools.Matcher protocol.
- :raises self.failureException: When matcher does not match thing.
- """
- mismatch = matcher.match(matchee)
- if not mismatch:
- return
- self.fail('Match failed. Matchee: "%s"\nMatcher: %s\nDifference: %s\n'
- % (matchee, matcher, mismatch.describe()))
-
- def defaultTestResult(self):
- return TestResult()
-
- def expectFailure(self, reason, predicate, *args, **kwargs):
- """Check that a test fails in a particular way.
-
- If the test fails in the expected way, a KnownFailure is caused. If it
- succeeds an UnexpectedSuccess is caused.
-
- The expected use of expectFailure is as a barrier at the point in a
- test where the test would fail. For example:
- >>> def test_foo(self):
- >>> self.expectFailure("1 should be 0", self.assertNotEqual, 1, 0)
- >>> self.assertEqual(1, 0)
-
- If in the future 1 were to equal 0, the expectFailure call can simply
- be removed. This separation preserves the original intent of the test
- while it is in the expectFailure mode.
- """
- self._add_reason(reason)
- try:
- predicate(*args, **kwargs)
- except self.failureException:
- exc_info = sys.exc_info()
- self.addDetail('traceback',
- content.TracebackContent(exc_info, self))
- raise _ExpectedFailure(exc_info)
- else:
- raise _UnexpectedSuccess(reason)
-
- def getUniqueInteger(self):
- """Get an integer unique to this test.
-
- Returns an integer that is guaranteed to be unique to this instance.
- Use this when you need an arbitrary integer in your test, or as a
- helper for custom anonymous factory methods.
- """
- return advance_iterator(self._unique_id_gen)
-
- def getUniqueString(self, prefix=None):
- """Get a string unique to this test.
-
- Returns a string that is guaranteed to be unique to this instance. Use
- this when you need an arbitrary string in your test, or as a helper
- for custom anonymous factory methods.
-
- :param prefix: The prefix of the string. If not provided, defaults
- to the id of the tests.
- :return: A bytestring of '<prefix>-<unique_int>'.
- """
- if prefix is None:
- prefix = self.id()
- return '%s-%d' % (prefix, self.getUniqueInteger())
-
- def onException(self, exc_info):
- """Called when an exception propogates from test code.
-
- :seealso addOnException:
- """
- for handler in self.__exception_handlers:
- handler(exc_info)
-
- @staticmethod
- def _report_error(self, result, err):
- self._report_traceback()
- result.addError(self, details=self.getDetails())
-
- @staticmethod
- def _report_expected_failure(self, result, err):
- result.addExpectedFailure(self, details=self.getDetails())
-
- @staticmethod
- def _report_failure(self, result, err):
- self._report_traceback()
- result.addFailure(self, details=self.getDetails())
-
- @staticmethod
- def _report_skip(self, result, err):
- if err.args:
- reason = err.args[0]
- else:
- reason = "no reason given."
- self._add_reason(reason)
- result.addSkip(self, details=self.getDetails())
-
- def _report_traceback(self):
- self.addDetail('traceback',
- content.TracebackContent(sys.exc_info(), self))
-
- @staticmethod
- def _report_unexpected_success(self, result, err):
- result.addUnexpectedSuccess(self, details=self.getDetails())
-
- def run(self, result=None):
- return self.__RunTest(self, self.exception_handlers).run(result)
-
- def _run_setup(self, result):
- """Run the setUp function for this test.
-
- :param result: A testtools.TestResult to report activity to.
- :raises ValueError: If the base class setUp is not called, a
- ValueError is raised.
- """
- self.setUp()
- if not self.__setup_called:
- raise ValueError(
- "TestCase.setUp was not called. Have you upcalled all the "
- "way up the hierarchy from your setUp? e.g. Call "
- "super(%s, self).setUp() from your setUp()."
- % self.__class__.__name__)
-
- def _run_teardown(self, result):
- """Run the tearDown function for this test.
-
- :param result: A testtools.TestResult to report activity to.
- :raises ValueError: If the base class tearDown is not called, a
- ValueError is raised.
- """
- self.tearDown()
- if not self.__teardown_called:
- raise ValueError(
- "TestCase.tearDown was not called. Have you upcalled all the "
- "way up the hierarchy from your tearDown? e.g. Call "
- "super(%s, self).tearDown() from your tearDown()."
- % self.__class__.__name__)
-
- def _run_test_method(self, result):
- """Run the test method for this test.
-
- :param result: A testtools.TestResult to report activity to.
- :return: None.
- """
- absent_attr = object()
- # Python 2.5+
- method_name = getattr(self, '_testMethodName', absent_attr)
- if method_name is absent_attr:
- # Python 2.4
- method_name = getattr(self, '_TestCase__testMethodName')
- testMethod = getattr(self, method_name)
- testMethod()
-
- def setUp(self):
- unittest.TestCase.setUp(self)
- self.__setup_called = True
-
- def tearDown(self):
- unittest.TestCase.tearDown(self)
- self.__teardown_called = True
-
-
-# Python 2.4 did not know how to copy functions.
-if types.FunctionType not in copy._copy_dispatch:
- copy._copy_dispatch[types.FunctionType] = copy._copy_immutable
-
-
-
-def clone_test_with_new_id(test, new_id):
- """Copy a TestCase, and give the copied test a new id.
-
- This is only expected to be used on tests that have been constructed but
- not executed.
- """
- newTest = copy.copy(test)
- newTest.id = lambda: new_id
- return newTest
-
-
-def skip(reason):
- """A decorator to skip unit tests.
-
- This is just syntactic sugar so users don't have to change any of their
- unit tests in order to migrate to python 2.7, which provides the
- @unittest.skip decorator.
- """
- def decorator(test_item):
- if wraps is not None:
- @wraps(test_item)
- def skip_wrapper(*args, **kwargs):
- raise TestCase.skipException(reason)
- else:
- def skip_wrapper(test_item):
- test_item.skip(reason)
- return skip_wrapper
- return decorator
-
-
-def skipIf(condition, reason):
- """Skip a test if the condition is true."""
- if condition:
- return skip(reason)
- def _id(obj):
- return obj
- return _id
-
-
-def skipUnless(condition, reason):
- """Skip a test unless the condition is true."""
- if not condition:
- return skip(reason)
- def _id(obj):
- return obj
- return _id