Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7e74384

Browse files
committed
- Fixed loading of tests by name when name refers to unbound
method (PyUnit issue 563882, thanks to Alexandre Fayolle) - Ignore non-callable attributes of classes when searching for test method names (PyUnit issue 769338, thanks to Seth Falcon) - New assertTrue and assertFalse aliases for comfort of JUnit users - Automatically discover 'runTest()' test methods (PyUnit issue 469444, thanks to Roeland Rengelink) - Dropped Python 1.5.2 compatibility, merged appropriate shortcuts from Python CVS; should work with Python >= 2.1. - Removed all references to string module by using string methods instead
1 parent 1e80359 commit 7e74384

1 file changed

Lines changed: 58 additions & 40 deletions

File tree

Lib/unittest.py

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def testMultiply(self):
2727
2828
http://pyunit.sourceforge.net/
2929
30-
Copyright (c) 1999, 2000, 2001 Steve Purcell
30+
Copyright (c) 1999-2003 Steve Purcell
3131
This module is free software, and you may redistribute it and/or modify
3232
it under the same terms as Python itself, so long as this copyright message
3333
and disclaimer are retained in their original form.
@@ -46,12 +46,11 @@ def testMultiply(self):
4646

4747
__author__ = "Steve Purcell"
4848
__email__ = "stephen_purcell at yahoo dot com"
49-
__version__ = "#Revision: 1.46 $"[11:-2]
49+
__version__ = "#Revision: 1.56 $"[11:-2]
5050

5151
import time
5252
import sys
5353
import traceback
54-
import string
5554
import os
5655
import types
5756

@@ -61,10 +60,26 @@ def testMultiply(self):
6160
__all__ = ['TestResult', 'TestCase', 'TestSuite', 'TextTestRunner',
6261
'TestLoader', 'FunctionTestCase', 'main', 'defaultTestLoader']
6362

64-
# Expose obsolete functions for backwards compatability
63+
# Expose obsolete functions for backwards compatibility
6564
__all__.extend(['getTestCaseNames', 'makeSuite', 'findTestCases'])
6665

6766

67+
##############################################################################
68+
# Backward compatibility
69+
##############################################################################
70+
if sys.version_info[:2] < (2, 2):
71+
False, True = 0, 1
72+
def isinstance(obj, clsinfo):
73+
import __builtin__
74+
if type(clsinfo) in (types.TupleType, types.ListType):
75+
for cls in clsinfo:
76+
if cls is type: cls = types.ClassType
77+
if __builtin__.isinstance(obj, cls):
78+
return 1
79+
return 0
80+
else: return __builtin__.isinstance(obj, clsinfo)
81+
82+
6883
##############################################################################
6984
# Test framework core
7085
##############################################################################
@@ -121,11 +136,11 @@ def wasSuccessful(self):
121136

122137
def stop(self):
123138
"Indicates that the tests should be aborted"
124-
self.shouldStop = 1
139+
self.shouldStop = True
125140

126141
def _exc_info_to_string(self, err):
127142
"""Converts a sys.exc_info()-style tuple of values into a string."""
128-
return string.join(traceback.format_exception(*err), '')
143+
return ''.join(traceback.format_exception(*err))
129144

130145
def __repr__(self):
131146
return "<%s run=%i errors=%i failures=%i>" % \
@@ -196,7 +211,7 @@ def shortDescription(self):
196211
the specified test method's docstring.
197212
"""
198213
doc = self.__testMethodDoc
199-
return doc and string.strip(string.split(doc, "\n")[0]) or None
214+
return doc and doc.split("\n")[0].strip() or None
200215

201216
def id(self):
202217
return "%s.%s" % (_strclass(self.__class__), self.__testMethodName)
@@ -209,9 +224,6 @@ def __repr__(self):
209224
(_strclass(self.__class__), self.__testMethodName)
210225

211226
def run(self, result=None):
212-
return self(result)
213-
214-
def __call__(self, result=None):
215227
if result is None: result = self.defaultTestResult()
216228
result.startTest(self)
217229
testMethod = getattr(self, self.__testMethodName)
@@ -224,10 +236,10 @@ def __call__(self, result=None):
224236
result.addError(self, self.__exc_info())
225237
return
226238

227-
ok = 0
239+
ok = False
228240
try:
229241
testMethod()
230-
ok = 1
242+
ok = True
231243
except self.failureException:
232244
result.addFailure(self, self.__exc_info())
233245
except KeyboardInterrupt:
@@ -241,11 +253,13 @@ def __call__(self, result=None):
241253
raise
242254
except:
243255
result.addError(self, self.__exc_info())
244-
ok = 0
256+
ok = False
245257
if ok: result.addSuccess(self)
246258
finally:
247259
result.stopTest(self)
248260

261+
__call__ = run
262+
249263
def debug(self):
250264
"""Run the test without collecting errors in a TestResult"""
251265
self.setUp()
@@ -292,7 +306,7 @@ def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
292306
else:
293307
if hasattr(excClass,'__name__'): excName = excClass.__name__
294308
else: excName = str(excClass)
295-
raise self.failureException, excName
309+
raise self.failureException, "%s not raised" % excName
296310

297311
def failUnlessEqual(self, first, second, msg=None):
298312
"""Fail if the two objects are unequal as determined by the '=='
@@ -334,6 +348,8 @@ def failIfAlmostEqual(self, first, second, places=7, msg=None):
334348
raise self.failureException, \
335349
(msg or '%s == %s within %s places' % (`first`, `second`, `places`))
336350

351+
# Synonyms for assertion methods
352+
337353
assertEqual = assertEquals = failUnlessEqual
338354

339355
assertNotEqual = assertNotEquals = failIfEqual
@@ -344,7 +360,9 @@ def failIfAlmostEqual(self, first, second, places=7, msg=None):
344360

345361
assertRaises = failUnlessRaises
346362

347-
assert_ = failUnless
363+
assert_ = assertTrue = failUnless
364+
365+
assertFalse = failIf
348366

349367

350368

@@ -369,7 +387,7 @@ def __repr__(self):
369387
def countTestCases(self):
370388
cases = 0
371389
for test in self._tests:
372-
cases = cases + test.countTestCases()
390+
cases += test.countTestCases()
373391
return cases
374392

375393
def addTest(self, test):
@@ -434,7 +452,7 @@ def __repr__(self):
434452
def shortDescription(self):
435453
if self.__description is not None: return self.__description
436454
doc = self.__testFunc.__doc__
437-
return doc and string.strip(string.split(doc, "\n")[0]) or None
455+
return doc and doc.split("\n")[0].strip() or None
438456

439457

440458

@@ -452,8 +470,10 @@ class TestLoader:
452470

453471
def loadTestsFromTestCase(self, testCaseClass):
454472
"""Return a suite of all tests cases contained in testCaseClass"""
455-
return self.suiteClass(map(testCaseClass,
456-
self.getTestCaseNames(testCaseClass)))
473+
testCaseNames = self.getTestCaseNames(testCaseClass)
474+
if not testCaseNames and hasattr(testCaseClass, 'runTest'):
475+
testCaseNames = ['runTest']
476+
return self.suiteClass(map(testCaseClass, testCaseNames))
457477

458478
def loadTestsFromModule(self, module):
459479
"""Return a suite of all tests cases contained in the given module"""
@@ -474,23 +494,20 @@ def loadTestsFromName(self, name, module=None):
474494
475495
The method optionally resolves the names relative to a given module.
476496
"""
477-
parts = string.split(name, '.')
497+
parts = name.split('.')
478498
if module is None:
479-
if not parts:
480-
raise ValueError, "incomplete test name: %s" % name
481-
else:
482-
parts_copy = parts[:]
483-
while parts_copy:
484-
try:
485-
module = __import__(string.join(parts_copy,'.'))
486-
break
487-
except ImportError:
488-
del parts_copy[-1]
489-
if not parts_copy: raise
499+
parts_copy = parts[:]
500+
while parts_copy:
501+
try:
502+
module = __import__('.'.join(parts_copy))
503+
break
504+
except ImportError:
505+
del parts_copy[-1]
506+
if not parts_copy: raise
490507
parts = parts[1:]
491508
obj = module
492509
for part in parts:
493-
obj = getattr(obj, part)
510+
parent, obj = obj, getattr(obj, part)
494511

495512
import unittest
496513
if type(obj) == types.ModuleType:
@@ -499,11 +516,13 @@ def loadTestsFromName(self, name, module=None):
499516
issubclass(obj, unittest.TestCase)):
500517
return self.loadTestsFromTestCase(obj)
501518
elif type(obj) == types.UnboundMethodType:
519+
return parent(obj.__name__)
502520
return obj.im_class(obj.__name__)
521+
elif isinstance(obj, unittest.TestSuite):
522+
return obj
503523
elif callable(obj):
504524
test = obj()
505-
if not isinstance(test, unittest.TestCase) and \
506-
not isinstance(test, unittest.TestSuite):
525+
if not isinstance(test, (unittest.TestCase, unittest.TestSuite)):
507526
raise ValueError, \
508527
"calling %s returned %s, not a test" % (obj,test)
509528
return test
@@ -514,16 +533,15 @@ def loadTestsFromNames(self, names, module=None):
514533
"""Return a suite of all tests cases found using the given sequence
515534
of string specifiers. See 'loadTestsFromName()'.
516535
"""
517-
suites = []
518-
for name in names:
519-
suites.append(self.loadTestsFromName(name, module))
536+
suites = [self.loadTestsFromName(name, module) for name in names]
520537
return self.suiteClass(suites)
521538

522539
def getTestCaseNames(self, testCaseClass):
523540
"""Return a sorted sequence of method names found within testCaseClass
524541
"""
525-
testFnNames = filter(lambda n,p=self.testMethodPrefix: n[:len(p)] == p,
526-
dir(testCaseClass))
542+
def isTestMethod(attrname, testCaseClass=testCaseClass, prefix=self.testMethodPrefix):
543+
return attrname[:len(prefix)] == prefix and callable(getattr(testCaseClass, attrname))
544+
testFnNames = filter(isTestMethod, dir(testCaseClass))
527545
for baseclass in testCaseClass.__bases__:
528546
for testFnName in self.getTestCaseNames(baseclass):
529547
if testFnName not in testFnNames: # handle overridden methods
@@ -706,7 +724,7 @@ def __init__(self, module='__main__', defaultTest=None,
706724
argv=None, testRunner=None, testLoader=defaultTestLoader):
707725
if type(module) == type(''):
708726
self.module = __import__(module)
709-
for part in string.split(module,'.')[1:]:
727+
for part in module.split('.')[1:]:
710728
self.module = getattr(self.module, part)
711729
else:
712730
self.module = module

0 commit comments

Comments
 (0)