Commit 32f531b9 authored by Nicolas Dumazet's avatar Nicolas Dumazet

backport some Python 2.7 unittest features to be able to use @skip


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@30086 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 9cbe95b6
# Backport of Python 2.7 unittest chosen parts to be able to use the
# "skip" decorators, and the associated ExpectedFailure and
# UnexpectedSuccess.
#
# Implementation is mostly a direct translation from Python r75708
# grep for "BACK" comments for backport-specific remarks.
import unittest
import sys
import time
class SkipTest(Exception):
"""
Raise this exception in a test to skip it.
Usually you can use TestResult.skip() or one of the skipping decorators
instead of raising this directly.
"""
pass
class _ExpectedFailure(Exception):
"""
Raise this when a test is expected to fail.
This is an implementation detail.
"""
def __init__(self, exc_info):
Exception.__init__(self)
self.exc_info = exc_info
class _UnexpectedSuccess(Exception):
"""
The test was supposed to fail, but it didn't!
"""
pass
def _id(obj):
return obj
def skip(reason):
"""
Unconditionally skip a test.
"""
def decorator(test_item):
if isinstance(test_item, type) and issubclass(test_item, TestCase):
test_item.__unittest_skip__ = True
test_item.__unittest_skip_why__ = reason
return test_item
def skip_wrapper(*args, **kwargs):
raise SkipTest(reason)
skip_wrapper.__name__ = test_item.__name__
skip_wrapper.__doc__ = test_item.__doc__
return skip_wrapper
return decorator
def skipIf(condition, reason):
"""
Skip a test if the condition is true.
"""
if condition:
return skip(reason)
return _id
def skipUnless(condition, reason):
"""
Skip a test unless the condition is true.
"""
if not condition:
return skip(reason)
return _id
def expectedFailure(func):
def wrapper(*args, **kwargs):
try:
func(*args, **kwargs)
except Exception:
raise _ExpectedFailure(sys.exc_info())
raise _UnexpectedSuccess
wrapper.__name__ = func.__name__
wrapper.__doc__ = func.__doc__
return wrapper
class TestCase(unittest.TestCase):
"""We only redefine here the run() method, and add a skipTest()
method.
"""
failureException = AssertionError
def run(self, result=None):
import pdb
#pdb.set_trace()
orig_result = result
if result is None:
result = self.defaultTestResult()
# BACK: Not necessary for Python < 2.7:
# TestResult.startTestRun does not exist yet
# startTestRun = getattr(result, 'startTestRun', None)
# if startTestRun is not None:
# startTestRun()
# BACK: Not needed for Python < 2.7
# unittest.addCleanup does not exist yet
# self._resultForDoCleanups = result
result.startTest(self)
if getattr(self.__class__, "__unittest_skip__", False):
# If the whole class was skipped.
try:
result.addSkip(self, self.__class__.__unittest_skip_why__)
finally:
result.stopTest(self)
return
# BACK: __testMethodName became _testMethodName in 2.7
testMethod = getattr(self, self.__testMethodName)
try:
success = False
try:
self.setUp()
except SkipTest, e:
result.addSkip(self, str(e))
except Exception:
result.addError(self, sys.exc_info())
else:
try:
testMethod()
except self.failureException:
result.addFailure(self, sys.exc_info())
except _ExpectedFailure, e:
result.addExpectedFailure(self, e.exc_info)
except _UnexpectedSuccess:
result.addUnexpectedSuccess(self)
except SkipTest, e:
result.addSkip(self, str(e))
except Exception:
result.addError(self, sys.exc_info())
else:
success = True
try:
self.tearDown()
except Exception:
result.addError(self, sys.exc_info())
success = False
# BACK: Not needed for Python < 2.7
# unittest.addCleanup does not exist yet
# cleanUpSuccess = self.doCleanups()
# success = success and cleanUpSuccess
if success:
result.addSuccess(self)
finally:
result.stopTest(self)
# BACK: Not necessary for Python < 2.7
# TestResult.stopTestRun does not exist yet
# if orig_result is None:
# stopTestRun = getattr(result, 'stopTestRun', None)
# if stopTestRun is not None:
# stopTestRun()
def skipTest(self, reason):
"""Skip this test."""
raise SkipTest(reason)
def defaultTestResult(self):
return TestResult()
def strclass(cls):
return "%s.%s" % (cls.__module__, cls.__name__)
class TestResult(unittest.TestResult):
def __init__(self):
super(TestResult, self).__init__()
self.skipped = []
self.expectedFailures = []
self.unexpectedSuccesses = []
def addSkip(self, test, reason):
"""Called when a test is skipped."""
self.skipped.append((test, reason))
def addExpectedFailure(self, test, err):
"""Called when an expected failure/error occured."""
self.expectedFailures.append(
(test, self._exc_info_to_string(err, test)))
def addUnexpectedSuccess(self, test):
"""Called when a test was expected to fail, but succeed."""
self.unexpectedSuccesses.append(test)
class _TextTestResult(unittest._TextTestResult, TestResult):
def __init__(self, stream, descriptions, verbosity):
# BACK: nice diamond!
# unittest.TestResult.__init__ is called twice here
unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
TestResult.__init__(self)
def addSkip(self, test, reason):
super(_TextTestResult, self).addSkip(test, reason)
if self.showAll:
self.stream.writeln("skipped %s" % repr(reason))
elif self.dots:
self.stream.write("s")
self.stream.flush()
def addExpectedFailure(self, test, err):
super(_TextTestResult, self).addExpectedFailure(test, err)
if self.showAll:
self.stream.writeln("expected failure")
elif self.dots:
self.stream.write("x")
self.stream.flush()
def addUnexpectedSuccess(self, test):
super(_TextTestResult, self).addUnexpectedSuccess(test)
if self.showAll:
self.stream.writeln("unexpected success")
elif self.dots:
self.stream.write("u")
self.stream.flush()
class TextTestRunner(unittest.TextTestRunner):
def _makeResult(self):
return _TextTestResult(self.stream, self.descriptions, self.verbosity)
def run(self, test):
result = self._makeResult()
startTime = time.time()
# BACK: 2.7 implementation wraps run with result.(start|stop)TestRun
test(result)
stopTime = time.time()
timeTaken = stopTime - startTime
result.printErrors()
self.stream.writeln(result.separator2)
run = result.testsRun
self.stream.writeln("Ran %d test%s in %.3fs" %
(run, run != 1 and "s" or "", timeTaken))
self.stream.writeln()
results = map(len, (result.expectedFailures,
result.unexpectedSuccesses,
result.skipped))
expectedFails, unexpectedSuccesses, skipped = results
infos = []
if not result.wasSuccessful():
self.stream.write("FAILED")
failed, errored = map(len, (result.failures, result.errors))
if failed:
infos.append("failures=%d" % failed)
if errored:
infos.append("errors=%d" % errored)
else:
self.stream.write("OK")
if skipped:
infos.append("skipped=%d" % skipped)
if expectedFails:
infos.append("expected failures=%d" % expectedFails)
if unexpectedSuccesses:
infos.append("unexpected successes=%d" % unexpectedSuccesses)
if infos:
self.stream.writeln(" (%s)" % (", ".join(infos),))
else:
self.stream.write("\n")
return result
# Tester
import unittest
# Implementation being tested
from backportUnittest import TestCase, TextTestRunner, skip, expectedFailure
class TestBackportUnittest(unittest.TestCase):
def setUp(self):
self.stream = open('/dev/null', 'w')
self.runner = TextTestRunner(self.stream)
def testSuccessfulTest(self):
class Success(TestCase):
def runTest(self):
self.assert_(True)
test_instance = Success()
result = self.runner.run(test_instance)
self.assertEquals(result.testsRun, 1)
self.assertEquals(len(result.errors), 0)
self.assertEquals(len(result.failures), 0)
self.assertEquals(len(result.expectedFailures), 0)
self.assertEquals(len(result.unexpectedSuccesses), 0)
self.assertEquals(len(result.skipped), 0)
self.assert_(result.wasSuccessful())
def testFailingTest(self):
class Failure(TestCase):
def runTest(self):
self.assert_(False)
test_instance = Failure()
result = self.runner.run(test_instance)
self.assertEquals(result.testsRun, 1)
self.assertEquals(len(result.errors), 0)
self.assertEquals(len(result.failures), 1)
self.assertEquals(len(result.expectedFailures), 0)
self.assertEquals(len(result.unexpectedSuccesses), 0)
self.assertEquals(len(result.skipped), 0)
self.assert_(not result.wasSuccessful())
def testSkippingUsingMethodDecorator(self):
class Skipped(TestCase):
@skip("Hey, let's skip this!")
def runTest(self):
self.assert_(False)
test_instance = Skipped()
result = self.runner.run(test_instance)
self.assertEquals(result.testsRun, 1)
self.assertEquals(len(result.errors), 0)
self.assertEquals(len(result.failures), 0)
self.assertEquals(len(result.expectedFailures), 0)
self.assertEquals(len(result.unexpectedSuccesses), 0)
self.assertEquals(len(result.skipped), 1)
self.assert_(result.wasSuccessful())
def testSkippingUsingClassDecorator(self):
class Skipped(TestCase):
def runTest(self):
self.assert_(False)
Skipped = skip("Class Skip?")(Skipped)
test_instance = Skipped()
result = self.runner.run(test_instance)
self.assertEquals(result.testsRun, 1)
self.assertEquals(len(result.errors), 0)
self.assertEquals(len(result.failures), 0)
self.assertEquals(len(result.expectedFailures), 0)
self.assertEquals(len(result.unexpectedSuccesses), 0)
self.assertEquals(len(result.skipped), 1)
self.assert_(result.wasSuccessful())
def testSkippingUsingSkipTest(self):
class Skipped(TestCase):
def runTest(self):
self.skipTest("Hey, let's skip this test!")
self.assert_(False)
test_instance = Skipped()
result = self.runner.run(test_instance)
self.assertEquals(result.testsRun, 1)
self.assertEquals(len(result.errors), 0)
self.assertEquals(len(result.failures), 0)
self.assertEquals(len(result.expectedFailures), 0)
self.assertEquals(len(result.unexpectedSuccesses), 0)
self.assertEquals(len(result.skipped), 1)
self.assert_(result.wasSuccessful())
def testExpectedFailure(self):
class WillFail(TestCase):
@expectedFailure
def runTest(self):
self.assert_(False)
test_instance = WillFail()
result = self.runner.run(test_instance)
self.assertEquals(result.testsRun, 1)
self.assertEquals(len(result.errors), 0)
self.assertEquals(len(result.failures), 0)
self.assertEquals(len(result.expectedFailures), 1)
self.assertEquals(len(result.unexpectedSuccesses), 0)
self.assertEquals(len(result.skipped), 0)
self.assert_(result.wasSuccessful())
def testUnExpectedSuccess(self):
class WillNotFail(TestCase):
@expectedFailure
def runTest(self):
self.assert_(True)
test_instance = WillNotFail()
result = self.runner.run(test_instance)
self.assertEquals(result.testsRun, 1)
self.assertEquals(len(result.errors), 0)
self.assertEquals(len(result.failures), 0)
self.assertEquals(len(result.expectedFailures), 0)
self.assertEquals(len(result.unexpectedSuccesses), 1)
self.assertEquals(len(result.skipped), 0)
# Unexpected success does not FAIL the test
self.assert_(result.wasSuccessful())
if __name__ == "__main__":
unittest.main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment