mirror of
https://github.com/python/cpython.git
synced 2025-07-30 14:44:10 +00:00
make class skipping decorators the same as skipping every test of the class
This removes ClassTestSuite and a good bit of hacks.
This commit is contained in:
parent
a7724e59e0
commit
176a56c69b
4 changed files with 26 additions and 64 deletions
|
@ -62,8 +62,7 @@ so a new fixture is created for each test.
|
||||||
|
|
||||||
Test suites are implemented by the :class:`TestSuite` class. This class allows
|
Test suites are implemented by the :class:`TestSuite` class. This class allows
|
||||||
individual tests and test suites to be aggregated; when the suite is executed,
|
individual tests and test suites to be aggregated; when the suite is executed,
|
||||||
all tests added directly to the suite and in "child" test suites are run. A
|
all tests added directly to the suite and in "child" test suites are run.
|
||||||
:class:`ClassTestSuite` contains the test cases of a class.
|
|
||||||
|
|
||||||
A test runner is an object that provides a single method,
|
A test runner is an object that provides a single method,
|
||||||
:meth:`~TestRunner.run`, which accepts a :class:`TestCase` or :class:`TestSuite`
|
:meth:`~TestRunner.run`, which accepts a :class:`TestCase` or :class:`TestSuite`
|
||||||
|
@ -1057,11 +1056,10 @@ Grouping tests
|
||||||
test suites that will be used to build the suite initially. Additional methods
|
test suites that will be used to build the suite initially. Additional methods
|
||||||
are provided to add test cases and suites to the collection later on.
|
are provided to add test cases and suites to the collection later on.
|
||||||
|
|
||||||
:class:`TestSuite` (including :class:`ClassTestSuite`) objects behave much
|
:class:`TestSuite` objects behave much like :class:`TestCase` objects, except
|
||||||
like :class:`TestCase` objects, except they do not actually implement a test.
|
they do not actually implement a test. Instead, they are used to aggregate
|
||||||
Instead, they are used to aggregate tests into groups of tests that should be
|
tests into groups of tests that should be run together. Some additional
|
||||||
run together. Some additional methods are available to add tests to
|
methods are available to add tests to :class:`TestSuite` instances:
|
||||||
:class:`TestSuite` instances:
|
|
||||||
|
|
||||||
|
|
||||||
.. method:: TestSuite.addTest(test)
|
.. method:: TestSuite.addTest(test)
|
||||||
|
@ -1118,14 +1116,6 @@ Grouping tests
|
||||||
is invoked by a :class:`TestRunner` rather than by the end-user test harness.
|
is invoked by a :class:`TestRunner` rather than by the end-user test harness.
|
||||||
|
|
||||||
|
|
||||||
.. class:: ClassTestSuite(tests, collected_from)
|
|
||||||
|
|
||||||
This subclass of :class:`TestSuite` repesents an aggregation of individuals
|
|
||||||
tests from one :class:`TestCase` class. *tests* is an iterable of
|
|
||||||
:class:`TestCase` instances created from the class. *collected_from* is the
|
|
||||||
class they came from.
|
|
||||||
|
|
||||||
|
|
||||||
Loading and running tests
|
Loading and running tests
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -1229,12 +1219,6 @@ Loading and running tests
|
||||||
This affects all the :meth:`loadTestsFrom\*` methods.
|
This affects all the :meth:`loadTestsFrom\*` methods.
|
||||||
|
|
||||||
|
|
||||||
.. attribute:: classSuiteClass
|
|
||||||
|
|
||||||
Callable object that constructs a test suite for the tests cases from one
|
|
||||||
class. The default value is :class:`ClassTestSuite`.
|
|
||||||
|
|
||||||
|
|
||||||
.. class:: TestResult
|
.. class:: TestResult
|
||||||
|
|
||||||
This class is used to compile information about which tests have succeeded
|
This class is used to compile information about which tests have succeeded
|
||||||
|
|
|
@ -107,7 +107,7 @@ class TestHashing(object):
|
||||||
# List subclass we can add attributes to.
|
# List subclass we can add attributes to.
|
||||||
class MyClassSuite(list):
|
class MyClassSuite(list):
|
||||||
|
|
||||||
def __init__(self, tests, klass):
|
def __init__(self, tests):
|
||||||
super(MyClassSuite, self).__init__(tests)
|
super(MyClassSuite, self).__init__(tests)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1262,7 +1262,7 @@ class Test_TestLoader(TestCase):
|
||||||
tests = [Foo('test_1'), Foo('test_2')]
|
tests = [Foo('test_1'), Foo('test_2')]
|
||||||
|
|
||||||
loader = unittest.TestLoader()
|
loader = unittest.TestLoader()
|
||||||
loader.classSuiteClass = MyClassSuite
|
loader.suiteClass = list
|
||||||
self.assertEqual(loader.loadTestsFromTestCase(Foo), tests)
|
self.assertEqual(loader.loadTestsFromTestCase(Foo), tests)
|
||||||
|
|
||||||
# It is implicit in the documentation for TestLoader.suiteClass that
|
# It is implicit in the documentation for TestLoader.suiteClass that
|
||||||
|
@ -1275,7 +1275,7 @@ class Test_TestLoader(TestCase):
|
||||||
def foo_bar(self): pass
|
def foo_bar(self): pass
|
||||||
m.Foo = Foo
|
m.Foo = Foo
|
||||||
|
|
||||||
tests = [unittest.ClassTestSuite([Foo('test_1'), Foo('test_2')], Foo)]
|
tests = [[Foo('test_1'), Foo('test_2')]]
|
||||||
|
|
||||||
loader = unittest.TestLoader()
|
loader = unittest.TestLoader()
|
||||||
loader.suiteClass = list
|
loader.suiteClass = list
|
||||||
|
@ -1294,7 +1294,7 @@ class Test_TestLoader(TestCase):
|
||||||
tests = [Foo('test_1'), Foo('test_2')]
|
tests = [Foo('test_1'), Foo('test_2')]
|
||||||
|
|
||||||
loader = unittest.TestLoader()
|
loader = unittest.TestLoader()
|
||||||
loader.classSuiteClass = MyClassSuite
|
loader.suiteClass = list
|
||||||
self.assertEqual(loader.loadTestsFromName('Foo', m), tests)
|
self.assertEqual(loader.loadTestsFromName('Foo', m), tests)
|
||||||
|
|
||||||
# It is implicit in the documentation for TestLoader.suiteClass that
|
# It is implicit in the documentation for TestLoader.suiteClass that
|
||||||
|
@ -1307,7 +1307,7 @@ class Test_TestLoader(TestCase):
|
||||||
def foo_bar(self): pass
|
def foo_bar(self): pass
|
||||||
m.Foo = Foo
|
m.Foo = Foo
|
||||||
|
|
||||||
tests = [unittest.ClassTestSuite([Foo('test_1'), Foo('test_2')], Foo)]
|
tests = [[Foo('test_1'), Foo('test_2')]]
|
||||||
|
|
||||||
loader = unittest.TestLoader()
|
loader = unittest.TestLoader()
|
||||||
loader.suiteClass = list
|
loader.suiteClass = list
|
||||||
|
@ -2871,7 +2871,7 @@ class Test_TestSkipping(TestCase):
|
||||||
def test_dont_skip(self): pass
|
def test_dont_skip(self): pass
|
||||||
test_do_skip = Foo("test_skip")
|
test_do_skip = Foo("test_skip")
|
||||||
test_dont_skip = Foo("test_dont_skip")
|
test_dont_skip = Foo("test_dont_skip")
|
||||||
suite = unittest.ClassTestSuite([test_do_skip, test_dont_skip], Foo)
|
suite = unittest.TestSuite([test_do_skip, test_dont_skip])
|
||||||
events = []
|
events = []
|
||||||
result = LoggingResult(events)
|
result = LoggingResult(events)
|
||||||
suite.run(result)
|
suite.run(result)
|
||||||
|
@ -2890,9 +2890,10 @@ class Test_TestSkipping(TestCase):
|
||||||
record.append(1)
|
record.append(1)
|
||||||
record = []
|
record = []
|
||||||
result = unittest.TestResult()
|
result = unittest.TestResult()
|
||||||
suite = unittest.ClassTestSuite([Foo("test_1")], Foo)
|
test = Foo("test_1")
|
||||||
|
suite = unittest.TestSuite([test])
|
||||||
suite.run(result)
|
suite.run(result)
|
||||||
self.assertEqual(result.skipped, [(suite, "testing")])
|
self.assertEqual(result.skipped, [(test, "testing")])
|
||||||
self.assertEqual(record, [])
|
self.assertEqual(record, [])
|
||||||
|
|
||||||
def test_expected_failure(self):
|
def test_expected_failure(self):
|
||||||
|
|
|
@ -59,7 +59,7 @@ import warnings
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# Exported classes and functions
|
# Exported classes and functions
|
||||||
##############################################################################
|
##############################################################################
|
||||||
__all__ = ['TestResult', 'TestCase', 'TestSuite', 'ClassTestSuite',
|
__all__ = ['TestResult', 'TestCase', 'TestSuite',
|
||||||
'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
|
'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
|
||||||
'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
|
'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
|
||||||
'expectedFailure']
|
'expectedFailure']
|
||||||
|
@ -458,6 +458,13 @@ class TestCase(object):
|
||||||
|
|
||||||
self._resultForDoCleanups = result
|
self._resultForDoCleanups = result
|
||||||
result.startTest(self)
|
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
|
||||||
testMethod = getattr(self, self._testMethodName)
|
testMethod = getattr(self, self._testMethodName)
|
||||||
try:
|
try:
|
||||||
success = False
|
success = False
|
||||||
|
@ -1110,37 +1117,6 @@ class TestSuite(object):
|
||||||
test.debug()
|
test.debug()
|
||||||
|
|
||||||
|
|
||||||
class ClassTestSuite(TestSuite):
|
|
||||||
"""
|
|
||||||
Suite of tests derived from a single TestCase class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, tests, class_collected_from):
|
|
||||||
super(ClassTestSuite, self).__init__(tests)
|
|
||||||
self.collected_from = class_collected_from
|
|
||||||
|
|
||||||
def id(self):
|
|
||||||
module = getattr(self.collected_from, "__module__", None)
|
|
||||||
if module is not None:
|
|
||||||
return "{0}.{1}".format(module, self.collected_from.__name__)
|
|
||||||
return self.collected_from.__name__
|
|
||||||
|
|
||||||
def run(self, result):
|
|
||||||
if getattr(self.collected_from, "__unittest_skip__", False):
|
|
||||||
# ClassTestSuite result pretends to be a TestCase enough to be
|
|
||||||
# reported.
|
|
||||||
result.startTest(self)
|
|
||||||
try:
|
|
||||||
result.addSkip(self, self.collected_from.__unittest_skip_why__)
|
|
||||||
finally:
|
|
||||||
result.stopTest(self)
|
|
||||||
else:
|
|
||||||
result = super(ClassTestSuite, self).run(result)
|
|
||||||
return result
|
|
||||||
|
|
||||||
shortDescription = id
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionTestCase(TestCase):
|
class FunctionTestCase(TestCase):
|
||||||
"""A test case that wraps a test function.
|
"""A test case that wraps a test function.
|
||||||
|
|
||||||
|
@ -1213,7 +1189,6 @@ class TestLoader(object):
|
||||||
testMethodPrefix = 'test'
|
testMethodPrefix = 'test'
|
||||||
sortTestMethodsUsing = cmp
|
sortTestMethodsUsing = cmp
|
||||||
suiteClass = TestSuite
|
suiteClass = TestSuite
|
||||||
classSuiteClass = ClassTestSuite
|
|
||||||
|
|
||||||
def loadTestsFromTestCase(self, testCaseClass):
|
def loadTestsFromTestCase(self, testCaseClass):
|
||||||
"""Return a suite of all tests cases contained in testCaseClass"""
|
"""Return a suite of all tests cases contained in testCaseClass"""
|
||||||
|
@ -1223,8 +1198,7 @@ class TestLoader(object):
|
||||||
testCaseNames = self.getTestCaseNames(testCaseClass)
|
testCaseNames = self.getTestCaseNames(testCaseClass)
|
||||||
if not testCaseNames and hasattr(testCaseClass, 'runTest'):
|
if not testCaseNames and hasattr(testCaseClass, 'runTest'):
|
||||||
testCaseNames = ['runTest']
|
testCaseNames = ['runTest']
|
||||||
suite = self.classSuiteClass(map(testCaseClass, testCaseNames),
|
suite = self.suiteClass(map(testCaseClass, testCaseNames))
|
||||||
testCaseClass)
|
|
||||||
return suite
|
return suite
|
||||||
|
|
||||||
def loadTestsFromModule(self, module):
|
def loadTestsFromModule(self, module):
|
||||||
|
|
|
@ -302,6 +302,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- In unittest, using a skipping decorator on a class is now equivalent to
|
||||||
|
skipping every test on the class. The ClassTestSuite class has been removed.
|
||||||
|
|
||||||
- Issue #6050: Don't fail extracting a directory from a zipfile if
|
- Issue #6050: Don't fail extracting a directory from a zipfile if
|
||||||
the directory already exists.
|
the directory already exists.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue