root / trunk / twisted / trial / unittest.py

Revision 26576, 62.2 kB (checked in by exarkun, 3 months ago)

Merge timeout-docs-3698

Author: cary
Reviewer: exarkun
Fixes: #3698

Correct the documentation for the trial timeout attribute. It may only be
a number of seconds or unset; setting it to None will result in a warning.

Line 
1 # -*- test-case-name: twisted.trial.test.test_tests -*-
2 # Copyright (c) 2001-2009 Twisted Matrix Laboratories.
3 # See LICENSE for details.
4
5 """
6 Things likely to be used by writers of unit tests.
7
8 Maintainer: Jonathan Lange
9 """
10
11
12 import doctest, inspect
13 import os, warnings, sys, tempfile, gc, types
14 from pprint import pformat
15 try:
16     from dis import findlinestarts as _findlinestarts
17 except ImportError:
18     # Definition copied from Python's Lib/dis.py - findlinestarts was not
19     # available in Python 2.3.  This function is copyright Python Software
20     # Foundation, released under the Python license:
21     # http://www.python.org/psf/license/
22     def _findlinestarts(code):
23         """Find the offsets in a byte code which are start of lines in the source.
24
25         Generate pairs (offset, lineno) as described in Python/compile.c.
26
27         """
28         byte_increments = [ord(c) for c in code.co_lnotab[0::2]]
29         line_increments = [ord(c) for c in code.co_lnotab[1::2]]
30
31         lastlineno = None
32         lineno = code.co_firstlineno
33         addr = 0
34         for byte_incr, line_incr in zip(byte_increments, line_increments):
35             if byte_incr:
36                 if lineno != lastlineno:
37                     yield (addr, lineno)
38                     lastlineno = lineno
39                 addr += byte_incr
40             lineno += line_incr
41         if lineno != lastlineno:
42             yield (addr, lineno)
43
44 from twisted.internet import defer, utils
45 from twisted.python import components, failure, log, monkey
46 from twisted.python.reflect import qual
47 from twisted.python.compat import set
48 from twisted.python import deprecate
49 from twisted.python.deprecate import getDeprecationWarningString
50
51 from twisted.trial import itrial, reporter, util
52
53 pyunit = __import__('unittest')
54
55 from zope.interface import implements
56
57
58
59 class SkipTest(Exception):
60     """
61     Raise this (with a reason) to skip the current test. You may also set
62     method.skip to a reason string to skip it, or set class.skip to skip the
63     entire TestCase.
64     """
65
66
67 class FailTest(AssertionError):
68     """Raised to indicate the current test has failed to pass."""
69
70
71 class Todo(object):
72     """
73     Internal object used to mark a L{TestCase} as 'todo'. Tests marked 'todo'
74     are reported differently in Trial L{TestResult}s. If todo'd tests fail,
75     they do not fail the suite and the errors are reported in a separate
76     category. If todo'd tests succeed, Trial L{TestResult}s will report an
77     unexpected success.
78     """
79
80     def __init__(self, reason, errors=None):
81         """
82         @param reason: A string explaining why the test is marked 'todo'
83
84         @param errors: An iterable of exception types that the test is
85         expected to raise. If one of these errors is raised by the test, it
86         will be trapped. Raising any other kind of error will fail the test.
87         If C{None} is passed, then all errors will be trapped.
88         """
89         self.reason = reason
90         self.errors = errors
91
92     def __repr__(self):
93         return "<Todo reason=%r errors=%r>" % (self.reason, self.errors)
94
95     def expected(self, failure):
96         """
97         @param failure: A L{twisted.python.failure.Failure}.
98
99         @return: C{True} if C{failure} is expected, C{False} otherwise.
100         """
101         if self.errors is None:
102             return True
103         for error in self.errors:
104             if failure.check(error):
105                 return True
106         return False
107
108
109 def makeTodo(value):
110     """
111     Return a L{Todo} object built from C{value}.
112
113     If C{value} is a string, return a Todo that expects any exception with
114     C{value} as a reason. If C{value} is a tuple, the second element is used
115     as the reason and the first element as the excepted error(s).
116
117     @param value: A string or a tuple of C{(errors, reason)}, where C{errors}
118     is either a single exception class or an iterable of exception classes.
119
120     @return: A L{Todo} object.
121     """
122     if isinstance(value, str):
123         return Todo(reason=value)
124     if isinstance(value, tuple):
125         errors, reason = value
126         try:
127             errors = list(errors)
128         except TypeError:
129             errors = [errors]
130         return Todo(reason=reason, errors=errors)
131
132
133
134 class _Warning(object):
135     """
136     A L{_Warning} instance represents one warning emitted through the Python
137     warning system (L{warnings}).  This is used to insulate callers of
138     L{_collectWarnings} from changes to the Python warnings system which might
139     otherwise require changes to the warning objects that function passes to
140     the observer object it accepts.
141
142     @ivar message: The string which was passed as the message parameter to
143         L{warnings.warn}.
144
145     @ivar category: The L{Warning} subclass which was passed as the category
146         parameter to L{warnings.warn}.
147
148     @ivar filename: The name of the file containing the definition of the code
149         object which was C{stacklevel} frames above the call to
150         L{warnings.warn}, where C{stacklevel} is the value of the C{stacklevel}
151         parameter passed to L{warnings.warn}.
152
153     @ivar lineno: The source line associated with the active instruction of the
154         code object object which was C{stacklevel} frames above the call to
155         L{warnings.warn}, where C{stacklevel} is the value of the C{stacklevel}
156         parameter passed to L{warnings.warn}.
157     """
158     def __init__(self, message, category, filename, lineno):
159         self.message = message
160         self.category = category
161         self.filename = filename
162         self.lineno = lineno
163
164
165
166 def _collectWarnings(observeWarning, f, *args, **kwargs):
167     """
168     Call C{f} with C{args} positional arguments and C{kwargs} keyword arguments
169     and collect all warnings which are emitted as a result in a list.
170
171     @param observeWarning: A callable which will be invoked with a L{_Warning}
172         instance each time a warning is emitted.
173
174     @return: The return value of C{f(*args, **kwargs)}.
175     """
176     def showWarning(message, category, filename, lineno, file=None, line=None):
177         assert isinstance(message, Warning)
178         observeWarning(_Warning(
179                 message.args[0], category, filename, lineno))
180
181     # Disable the per-module cache for every module otherwise if the warning
182     # which the caller is expecting us to collect was already emitted it won't
183     # be re-emitted by the call to f which happens below.
184     for v in sys.modules.itervalues():
185         if v is not None:
186             try:
187                 v.__warningregistry__ = None
188             except:
189                 # Don't specify a particular exception type to handle in case
190                 # some wacky object raises some wacky exception in response to
191                 # the setattr attempt.
192                 pass
193
194     origFilters = warnings.filters[:]
195     origShow = warnings.showwarning
196     warnings.simplefilter('always')
197     try:
198         warnings.showwarning = showWarning
199         result = f(*args, **kwargs)
200     finally:
201         warnings.filters[:] = origFilters
202         warnings.showwarning = origShow
203     return result
204
205
206
207 class _Assertions(pyunit.TestCase, object):
208     """
209     Replaces many of the built-in TestCase assertions. In general, these
210     assertions provide better error messages and are easier to use in
211     callbacks. Also provides new assertions such as L{failUnlessFailure}.
212
213     Although the tests are defined as 'failIf*' and 'failUnless*', they can
214     also be called as 'assertNot*' and 'assert*'.
215     """
216
217     def fail(self, msg=None):
218         """
219         Absolutely fail the test.  Do not pass go, do not collect $200.
220
221         @param msg: the message that will be displayed as the reason for the
222         failure
223         """
224         raise self.failureException(msg)
225
226     def failIf(self, condition, msg=None):
227         """
228         Fail the test if C{condition} evaluates to True.
229
230         @param condition: any object that defines __nonzero__
231         """
232         if condition:
233             raise self.failureException(msg)
234         return condition
235     assertNot = assertFalse = failUnlessFalse = failIf
236
237     def failUnless(self, condition, msg=None):
238         """
239         Fail the test if C{condition} evaluates to False.
240
241         @param condition: any object that defines __nonzero__
242         """
243         if not condition:
244             raise self.failureException(msg)
245         return condition
246     assert_ = assertTrue = failUnlessTrue = failUnless
247
248     def failUnlessRaises(self, exception, f, *args, **kwargs):
249         """
250         Fail the test unless calling the function C{f} with the given
251         C{args} and C{kwargs} raises C{exception}. The failure will report
252         the traceback and call stack of the unexpected exception.
253
254         @param exception: exception type that is to be expected
255         @param f: the function to call
256
257         @return: The raised exception instance, if it is of the given type.
258         @raise self.failureException: Raised if the function call does
259             not raise an exception or if it raises an exception of a
260             different type.
261         """
262         try:
263             result = f(*args, **kwargs)
264         except exception, inst:
265             return inst
266         except:
267             raise self.failureException('%s raised instead of %s:\n %s'
268                                         % (sys.exc_info()[0],
269                                            exception.__name__,
270                                            failure.Failure().getTraceback()))
271         else:
272             raise self.failureException('%s not raised (%r returned)'
273                                         % (exception.__name__, result))
274     assertRaises = failUnlessRaises
275
276     def failUnlessEqual(self, first, second, msg=''):
277         """
278         Fail the test if C{first} and C{second} are not equal.
279
280         @param msg: A string describing the failure that's included in the
281             exception.
282         """
283         if not first == second:
284             if msg is None:
285                 msg = ''
286             if len(msg) > 0:
287                 msg += '\n'
288             raise self.failureException(
289                 '%snot equal:\na = %s\nb = %s\n'
290                 % (msg, pformat(first), pformat(second)))
291         return first
292     assertEqual = assertEquals = failUnlessEquals = failUnlessEqual
293
294     def failUnlessIdentical(self, first, second, msg=None):
295         """
296         Fail the test if C{first} is not C{second}.  This is an
297         obect-identity-equality test, not an object equality
298         (i.e. C{__eq__}) test.
299
300         @param msg: if msg is None, then the failure message will be
301         '%r is not %r' % (first, second)
302         """
303         if first is not second:
304             raise self.failureException(msg or '%r is not %r' % (first, second))
305         return first
306     assertIdentical = failUnlessIdentical
307
308     def failIfIdentical(self, first, second, msg=None):
309         """
310         Fail the test if C{first} is C{second}.  This is an
311         obect-identity-equality test, not an object equality
312         (i.e. C{__eq__}) test.
313
314         @param msg: if msg is None, then the failure message will be
315         '%r is %r' % (first, second)
316         """
317         if first is second:
318             raise self.failureException(msg or '%r is %r' % (first, second))
319         return first
320     assertNotIdentical = failIfIdentical
321
322     def failIfEqual(self, first, second, msg=None):
323         """
324         Fail the test if C{first} == C{second}.
325
326         @param msg: if msg is None, then the failure message will be
327         '%r == %r' % (first, second)
328         """
329         if not first != second:
330             raise self.failureException(msg or '%r == %r' % (first, second))
331         return first
332     assertNotEqual = assertNotEquals = failIfEquals = failIfEqual
333
334     def failUnlessIn(self, containee, container, msg=None):
335         """
336         Fail the test if C{containee} is not found in C{container}.
337
338         @param containee: the value that should be in C{container}
339         @param container: a sequence type, or in the case of a mapping type,
340                           will follow semantics of 'if key in dict.keys()'
341         @param msg: if msg is None, then the failure message will be
342                     '%r not in %r' % (first, second)
343         """
344         if containee not in container:
345             raise self.failureException(msg or "%r not in %r"
346                                         % (containee, container))
347         return containee
348     assertIn = failUnlessIn
349
350     def failIfIn(self, containee, container, msg=None):
351         """
352         Fail the test if C{containee} is found in C{container}.
353
354         @param containee: the value that should not be in C{container}
355         @param container: a sequence type, or in the case of a mapping type,
356                           will follow semantics of 'if key in dict.keys()'
357         @param msg: if msg is None, then the failure message will be
358                     '%r in %r' % (first, second)
359         """
360         if containee in container:
361             raise self.failureException(msg or "%r in %r"
362                                         % (containee, container))
363         return containee
364     assertNotIn = failIfIn
365
366     def failIfAlmostEqual(self, first, second, places=7, msg=None):
367         """
368         Fail if the two objects are equal as determined by their
369         difference rounded to the given number of decimal places
370         (default 7) and comparing to zero.
371
372         @note: decimal places (from zero) is usually not the same
373                as significant digits (measured from the most
374                signficant digit).
375
376         @note: included for compatiblity with PyUnit test cases
377         """
378         if round(second-first, places) == 0:
379             raise self.failureException(msg or '%r == %r within %r places'
380                                         % (first, second, places))
381         return first
382     assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual
383     failIfAlmostEquals = failIfAlmostEqual
384
385     def failUnlessAlmostEqual(self, first, second, places=7, msg=None):
386         """
387         Fail if the two objects are unequal as determined by their
388         difference rounded to the given number of decimal places
389         (default 7) and comparing to zero.
390
391         @note: decimal places (from zero) is usually not the same
392                as significant digits (measured from the most
393                signficant digit).
394
395         @note: included for compatiblity with PyUnit test cases
396         """
397         if round(second-first, places) != 0:
398             raise self.failureException(msg or '%r != %r within %r places'
399                                         % (first, second, places))
400         return first
401     assertAlmostEqual = assertAlmostEquals = failUnlessAlmostEqual
402     failUnlessAlmostEquals = failUnlessAlmostEqual
403
404     def failUnlessApproximates(self, first, second, tolerance, msg=None):
405         """
406         Fail if C{first} - C{second} > C{tolerance}
407
408         @param msg: if msg is None, then the failure message will be
409                     '%r ~== %r' % (first, second)
410         """
411         if abs(first - second) > tolerance:
412             raise self.failureException(msg or "%s ~== %s" % (first, second))
413         return first
414     assertApproximates = failUnlessApproximates
415
416     def failUnlessFailure(self, deferred, *expectedFailures):
417         """
418         Fail if C{deferred} does not errback with one of C{expectedFailures}.
419         Returns the original Deferred with callbacks added. You will need
420         to return this Deferred from your test case.
421         """
422         def _cb(ignore):
423             raise self.failureException(
424                 "did not catch an error, instead got %r" % (ignore,))
425
426         def _eb(failure):
427             if failure.check(*expectedFailures):
428                 return failure.value
429             else:
430                 output = ('\nExpected: %r\nGot:\n%s'
431                           % (expectedFailures, str(failure)))
432                 raise self.failureException(output)
433         return deferred.addCallbacks(_cb, _eb)
434     assertFailure = failUnlessFailure
435
436     def failUnlessSubstring(self, substring, astring, msg=None):
437         """
438         Fail if C{substring} does not exist within C{astring}.
439         """
440         return self.failUnlessIn(substring, astring, msg)
441     assertSubstring = failUnlessSubstring
442
443     def failIfSubstring(self, substring, astring, msg=None):
444         """
445         Fail if C{astring} contains C{substring}.
446         """
447         return self.failIfIn(substring, astring, msg)
448     assertNotSubstring = failIfSubstring
449
450     def failUnlessWarns(self, category, message, filename, f,
451                        *args, **kwargs):
452         """
453         Fail if the given function doesn't generate the specified warning when
454         called. It calls the function, checks the warning, and forwards the
455         result of the function if everything is fine.
456
457         @param category: the category of the warning to check.
458         @param message: the output message of the warning to check.
459         @param filename: the filename where the warning should come from.
460         @param f: the function which is supposed to generate the warning.
461         @type f: any callable.
462         @param args: the arguments to C{f}.
463         @param kwargs: the keywords arguments to C{f}.
464
465         @return: the result of the original function C{f}.
466         """
467         warningsShown = []
468         result = _collectWarnings(warningsShown.append, f, *args, **kwargs)
469
470         if not warningsShown:
471             self.fail("No warnings emitted")
472         first = warningsShown[0]
473         for other in warningsShown[1:]:
474             if ((other.message, other.category)
475                 != (first.message, first.category)):
476                 self.fail("Can't handle different warnings")
477         self.assertEqual(first.message, message)
478         self.assertIdentical(first.category, category)
479
480         # Use starts with because of .pyc/.pyo issues.
481         self.failUnless(
482             filename.startswith(first.filename),
483             'Warning in %r, expected %r' % (first.filename, filename))
484
485         # It would be nice to be able to check the line number as well, but
486         # different configurations actually end up reporting different line
487         # numbers (generally the variation is only 1 line, but that's enough
488         # to fail the test erroneously...).
489         # self.assertEqual(lineno, xxx)
490
491         return result
492     assertWarns = failUnlessWarns
493
494     def failUnlessIsInstance(self, instance, classOrTuple):
495         """
496         Fail if C{instance} is not an instance of the given class or of
497         one of the given classes.
498
499         @param instance: the object to test the type (first argument of the
500             C{isinstance} call).
501         @type instance: any.
502         @param classOrTuple: the class or classes to test against (second
503             argument of the C{isinstance} call).
504         @type classOrTuple: class, type, or tuple.
505         """
506         if not isinstance(instance, classOrTuple):
507             self.fail("%r is not an instance of %s" % (instance, classOrTuple))
508     assertIsInstance = failUnlessIsInstance
509
510     def failIfIsInstance(self, instance, classOrTuple):
511         """
512         Fail if C{instance} is not an instance of the given class or of
513         one of the given classes.
514
515         @param instance: the object to test the type (first argument of the
516             C{isinstance} call).
517         @type instance: any.
518         @param classOrTuple: the class or classes to test against (second
519             argument of the C{isinstance} call).
520         @type classOrTuple: class, type, or tuple.
521         """
522         if isinstance(instance, classOrTuple):
523             self.fail("%r is an instance of %s" % (instance, classOrTuple))
524     assertNotIsInstance = failIfIsInstance
525
526
527 class _LogObserver(object):
528     """
529     Observes the Twisted logs and catches any errors.
530
531     @ivar _errors: A C{list} of L{Failure} instances which were received as
532         error events from the Twisted logging system.
533
534     @ivar _added: A C{int} giving the number of times C{_add} has been called
535         less the number of times C{_remove} has been called; used to only add
536         this observer to the Twisted logging since once, regardless of the
537         number of calls to the add method.
538
539     @ivar _ignored: A C{list} of exception types which will not be recorded.
540     """
541
542     def __init__(self):
543         self._errors = []
544         self._added = 0
545         self._ignored = []
546
547
548     def _add(self):
549         if self._added == 0:
550             log.addObserver(self.gotEvent)
551             self._oldFE, log._flushErrors = (log._flushErrors, self.flushErrors)
552             self._oldIE, log._ignore = (log._ignore, self._ignoreErrors)
553             self._oldCI, log._clearIgnores = (log._clearIgnores,
554                                               self._clearIgnores)
555         self._added += 1
556
557     def _remove(self):
558         self._added -= 1
559         if self._added == 0:
560             log.removeObserver(self.gotEvent)
561             log._flushErrors = self._oldFE
562             log._ignore = self._oldIE
563             log._clearIgnores = self._oldCI
564
565
566     def _ignoreErrors(self, *errorTypes):
567         """
568         Do not store any errors with any of the given types.
569         """
570         self._ignored.extend(errorTypes)
571
572
573     def _clearIgnores(self):
574         """
575         Stop ignoring any errors we might currently be ignoring.
576         """
577         self._ignored = []
578
579
580     def flushErrors(self, *errorTypes):
581         """
582         Flush errors from the list of caught errors. If no arguments are
583         specified, remove all errors. If arguments are specified, only remove
584         errors of those types from the stored list.
585         """
586         if errorTypes:
587             flushed = []
588             remainder = []
589             for f in self._errors:
590                 if f.check(*errorTypes):
591                     flushed.append(f)
592                 else:
593                     remainder.append(f)
594             self._errors = remainder
595         else:
596             flushed = self._errors
597             self._errors = []
598         return flushed
599
600
601     def getErrors(self):
602         """
603         Return a list of errors caught by this observer.
604         """
605         return self._errors
606
607
608     def gotEvent(self, event):
609         """
610         The actual observer method. Called whenever a message is logged.
611
612         @param event: A dictionary containing the log message. Actual
613         structure undocumented (see source for L{twisted.python.log}).
614         """
615         if event.get('isError', False) and 'failure' in event:
616             f = event['failure']
617             if len(self._ignored) == 0 or not f.check(*self._ignored):
618                 self._errors.append(f)
619
620
621
622 _logObserver = _LogObserver()
623
624 _wait_is_running = []
625
626 _classFixturesDeprecationMessage = (
627     "%(method)s, deprecated since Twisted 8.2.0, was overridden by "
628     "%(class)s.  Use %(replace)s instead.")
629
630 class TestCase(_Assertions):
631     """
632     A unit test. The atom of the unit testing universe.
633
634     This class extends C{unittest.TestCase} from the standard library. The
635     main feature is the ability to return C{Deferred}s from tests and fixture
636     methods and to have the suite wait for those C{Deferred}s to fire.
637
638     To write a unit test, subclass C{TestCase} and define a method (say,
639     'test_foo') on the subclass. To run the test, instantiate your subclass
640     with the name of the method, and call L{run} on the instance, passing a
641     L{TestResult} object.
642
643     The C{trial} script will automatically find any C{TestCase} subclasses
644     defined in modules beginning with 'test_' and construct test cases for all
645     methods beginning with 'test'.
646
647     If an error is logged during the test run, the test will fail with an
648     error. See L{log.err}.
649
650     @ivar failureException: An exception class, defaulting to C{FailTest}. If
651     the test method raises this exception, it will be reported as a failure,
652     rather than an exception. All of the assertion methods raise this if the
653     assertion fails.
654
655     @ivar skip: C{None} or a string explaining why this test is to be
656     skipped. If defined, the test will not be run. Instead, it will be
657     reported to the result object as 'skipped' (if the C{TestResult} supports
658     skipping).
659
660     @ivar suppress: C{None} or a list of tuples of C{(args, kwargs)} to be
661     passed to C{warnings.filterwarnings}. Use these to suppress warnings
662     raised in a test. Useful for testing deprecated code. See also
663     L{util.suppress}.
664
665     @ivar timeout: A real number of seconds. If set, the test will
666     raise an error if it takes longer than C{timeout} seconds.
667     If not set, util.DEFAULT_TIMEOUT_DURATION is used.
668
669     @ivar todo: C{None}, a string or a tuple of C{(errors, reason)} where
670     C{errors} is either an exception class or an iterable of exception
671     classes, and C{reason} is a string. See L{Todo} or L{makeTodo} for more
672     information.
673
674     @ivar _suppressUpDownWarning: Private flag used by tests for C{setUpClass}
675         and C{tearDownClass} to suppress the deprecation warnings for these
676         methods.  This is necessary since the normal warning suppression
677         mechanism does not work for these warnings.  No code should use this
678         flag aside from tests for these methods.  When support for the methods
679         is removed altogether, so should this flag be removed.
680     """
681
682     implements(itrial.ITestCase)
683     failureException = FailTest
684
685     def __init__(self, methodName='runTest'):
686         """
687         Construct an asynchronous test case for C{methodName}.
688
689         @param methodName: The name of a method on C{self}. This method should
690         be a unit test. That is, it should be a short method that calls some of
691         the assert* methods. If C{methodName} is unspecified, L{runTest} will
692         be used as the test method. This is mostly useful for testing Trial.
693         """
694         super(TestCase, self).__init__(methodName)
695         self._testMethodName = methodName
696         testMethod = getattr(self, methodName)
697         self._parents = [testMethod, self]
698         self._parents.extend(util.getPythonContainers(testMethod))
699         self._shared = (hasattr(self, 'setUpClass') or
700                         hasattr(self, 'tearDownClass'))
701         if self._shared:
702             self._prepareClassFixture()
703             if not hasattr(self.__class__, '_instances'):
704                 self._initInstances()
705             self.__class__._instances.add(self)
706         self._passed = False
707         self._cleanups = []
708
709     def _initInstances(cls):
710         cls._instances = set()
711         cls._instancesRun = set()
712     _initInstances = classmethod(_initInstances)
713
714     if sys.version_info >= (2, 6):
715         # Override the comparison defined by the base TestCase which considers
716         # instances of the same class with the same _testMethodName to be
717         # equal.  Since trial puts TestCase instances into a set, that
718         # definition of comparison makes it impossible to run the same test
719         # method twice.  Most likely, trial should stop using a set to hold
720         # tests, but until it does, this is necessary on Python 2.6.  Only
721         # __eq__ and __ne__ are required here, not __hash__, since the
722         # inherited __hash__ is compatible with these equality semantics.  A
723         # different __hash__ might be slightly more efficient (by reducing
724         # collisions), but who cares? -exarkun
725         def __eq__(self, other):
726             return self is other
727
728         def __ne__(self, other):
729             return self is not other
730
731
732
733     def _isFirst(self):
734         return len(self.__class__._instancesRun) == 0
735
736     def _isLast(self):
737         return self.__class__._instancesRun == self.__class__._instances
738
739     def _prepareClassFixture(self):
740         """Lots of tests assume that test methods all run in the same instance
741         of TestCase.  This isn't true. Calling this method ensures that
742         self.__class__._testCaseInstance contains an instance of this class
743         that will remain the same for all tests from this class.
744         """
745         if not hasattr(self.__class__, '_testCaseInstance'):
746             self.__class__._testCaseInstance = self
747         if self.__class__._testCaseInstance.__class__ != self.__class__:
748             self.__class__._testCaseInstance = self
749
750     def _run(self, methodName, result):
751         from twisted.internet import reactor
752         timeout = self.getTimeout()
753         def onTimeout(d):
754             e = defer.TimeoutError("%r (%s) still running at %s secs"
755                 % (self, methodName, timeout))
756             f = failure.Failure(e)
757             # try to errback the deferred that the test returns (for no gorram
758             # reason) (see issue1005 and test_errorPropagation in
759             # test_deferred)
760             try:
761                 d.errback(f)
762             except defer.AlreadyCalledError:
763                 # if the deferred has been called already but the *back chain
764                 # is still unfinished, crash the reactor and report timeout
765                 # error ourself.
766                 reactor.crash()
767                 self._timedOut = True # see self._wait
768                 todo = self.getTodo()
769                 if todo is not None and todo.expected(f):
770                     result.addExpectedFailure(self, f, todo)
771                 else:
772                     result.addError(self, f)
773         onTimeout = utils.suppressWarnings(
774             onTimeout, util.suppress(category=DeprecationWarning))
775         if self._shared:
776             test = self.__class__._testCaseInstance
777         else:
778             test = self
779         method = getattr(test, methodName)
780         d = defer.maybeDeferred(utils.runWithWarningsSuppressed,
781                                 self.getSuppress(), method)
782         call = reactor.callLater(timeout, onTimeout, d)
783         d.addBoth(lambda x : call.active() and call.cancel() or x)
784         return d
785
786     def shortDescription(self):
787         desc = super(TestCase, self).shortDescription()
788         if desc is None:
789             return self._testMethodName
790         return desc
791
792     def __call__(self, *args, **kwargs):
793         return self.run(*args, **kwargs)
794
795     def deferSetUpClass(self, result):
796         """
797         Run the per-class set up fixture, C{setUpClass}, for this test case.
798
799         This must be called only once per TestCase subclass, since it will
800         run the fixture unconditionally.
801
802         @type result: L{IReporter} provider
803         @param result: The result which will be used to report any problems
804             encountered in C{setUpClass}.
805
806         @return: A L{Deferred} which will fire with the result of
807             C{setUpClass} or with C{None} if there is no C{setUpClass}
808             defined.
809         """
810         if not hasattr(self, 'setUpClass'):
811             d = defer.succeed(None)
812             d.addCallback(self.deferSetUp, result)
813             return d
814         if not getattr(self, '_suppressUpDownWarning', None):
815             warn = deprecate.getWarningMethod()
816             warn(_classFixturesDeprecationMessage % {
817                     'method': 'setUpClass',
818                     'class': qual(self.__class__),
819                     'replace': 'setUp'},
820                 category=DeprecationWarning,
821                 stacklevel=0)
822         d = self._run('setUpClass', result)
823         d.addCallbacks(self.deferSetUp, self._ebDeferSetUpClass,
824                        callbackArgs=(result,),
825                        errbackArgs=(result,))
826         return d
827
828     def _ebDeferSetUpClass(self, error, result):
829         if error.check(SkipTest):
830             result.addSkip(self, self._getReason(error))
831             self.__class__._instancesRun.remove(self)
832         elif error.check(KeyboardInterrupt):
833             result.stop()
834         else:
835             result.addError(self, error)
836             self.__class__._instancesRun.remove(self)
837
838     def deferSetUp(self, ignored, result):
839         d = self._run('setUp', result)
840         d.addCallbacks(self.deferTestMethod, self._ebDeferSetUp,
841                        callbackArgs=(result,),
842                        errbackArgs=(result,))
843         return d
844
845     def _ebDeferSetUp(self, failure, result):
846         if failure.check(SkipTest):
847             result.addSkip(self, self._getReason(failure))
848         else:
849             result.addError(self, failure)
850             if failure.check(KeyboardInterrupt):
851                 result.stop()
852         return self.deferRunCleanups(None, result)
853
854     def deferTestMethod(self, ignored, result):
855         d = self._run(self._testMethodName, result)
856         d.addCallbacks(self._cbDeferTestMethod, self._ebDeferTestMethod,
857                        callbackArgs=(result,),
858                        errbackArgs=(result,))
859         d.addBoth(self.deferRunCleanups, result)
860         d.addBoth(self.deferTearDown, result)
861         if self._shared and hasattr(self, 'tearDownClass') and self._isLast():
862             d.addBoth(self.deferTearDownClass, result)
863         return d
864
865     def _cbDeferTestMethod(self, ignored, result):
866         if self.getTodo() is not None:
867             result.addUnexpectedSuccess(self, self.getTodo())
868         else:
869             self._passed = True
870         return ignored
871
872     def _ebDeferTestMethod(self, f, result):
873         todo = self.getTodo()
874         if todo is not None and todo.expected(f):
875             result.addExpectedFailure(self, f, todo)
876         elif f.check(self.failureException, FailTest):
877             result.addFailure(self, f)
878         elif f.check(KeyboardInterrupt):
879             result.addError(self, f)
880             result.stop()
881         elif f.check(SkipTest):
882             result.addSkip(self, self._getReason(f))
883         else:
884             result.addError(self, f)
885
886     def deferTearDown(self, ignored, result):
887         d = self._run('tearDown', result)
888         d.addErrback(self._ebDeferTearDown, result)
889         return d
890
891     def _ebDeferTearDown(self, failure, result):
892         result.addError(self, failure)
893         if failure.check(KeyboardInterrupt):
894             result.stop()
895         self._passed = False
896
897     def deferRunCleanups(self, ignored, result):
898         """
899         Run any scheduled cleanups and report errors (if any to the result
900         object.
901         """
902         d = self._runCleanups()
903         d.addCallback(self._cbDeferRunCleanups, result)
904         return d
905
906     def _cbDeferRunCleanups(self, cleanupResults, result):
907         for flag, failure in cleanupResults:
908             if flag == defer.FAILURE:
909                 result.addError(self, failure)
910                 if failure.check(KeyboardInterrupt):
911                     result.stop()
912                 self._passed = False
913
914     def deferTearDownClass(self, ignored, result):
915         """
916         Run the per-class tear down fixture, C{tearDownClass}, for this test
917         case.
918
919         This must be called only once per TestCase subclass, since it will
920         run the fixture unconditionally.  This must not be called if there
921         is no C{tearDownClass} method.
922
923         @param ignored: An ignored parameter.
924
925         @type result: L{IReporter} provider
926         @param result: The result which will be used to report any problems
927             encountered in C{tearDownClass}.
928
929         @return: A L{Deferred} which will fire with the result of
930             C{tearDownClass}.
931         """
932         if not getattr(self, '_suppressUpDownWarning', None):
933             warn = deprecate.getWarningMethod()
934             warn(_classFixturesDeprecationMessage % {
935                     'method': 'tearDownClass',
936                     'class': qual(self.__class__),
937                     'replace': 'tearDown'},
938                 category=DeprecationWarning,
939                 stacklevel=1)
940         d = self._run('tearDownClass', result)
941         d.addErrback(self._ebTearDownClass, result)
942         return d
943
944     def _ebTearDownClass(self, error, result):
945         if error.check(KeyboardInterrupt):
946             result.stop()
947         result.addError(self, error)
948
949     def _cleanUp(self, result):
950         try:
951             clean = util._Janitor(self, result).postCaseCleanup()
952             if not clean:
953                 self._passed = False
954         except:
955             result.addError(self, failure.Failure())
956             self._passed = False
957         for error in self._observer.getErrors():
958             result.addError(self, error)
959             self._passed = False
960         self.flushLoggedErrors()
961         self._removeObserver()
962         if self._passed:
963             result.addSuccess(self)
964
965     def _classCleanUp(self, result):
966         try:
967             util._Janitor(self, result).postClassCleanup()
968         except:
969             result.addError(self, failure.Failure())
970
971     def _makeReactorMethod(self, name):
972         """
973         Create a method which wraps the reactor method C{name}. The new
974         method issues a deprecation warning and calls the original.
975         """
976         def _(*a, **kw):
977             warnings.warn("reactor.%s cannot be used inside unit tests. "
978                           "In the future, using %s will fail the test and may "
979                           "crash or hang the test run."
980                           % (name, name),
981                           stacklevel=2, category=DeprecationWarning)
982             return self._reactorMethods[name](*a, **kw)
983         return _
984
985     def _deprecateReactor(self, reactor):
986         """
987         Deprecate C{iterate}, C{crash} and C{stop} on C{reactor}. That is,
988         each method is wrapped in a function that issues a deprecation
989         warning, then calls the original.
990
991         @param reactor: The Twisted reactor.
992         """
993         self._reactorMethods = {}
994         for name in ['crash', 'iterate', 'stop']:
995             self._reactorMethods[name] = getattr(reactor, name)
996             setattr(reactor, name, self._makeReactorMethod(name))
997
998     def _undeprecateReactor(self, reactor):
999         """
1000         Restore the deprecated reactor methods. Undoes what
1001         L{_deprecateReactor} did.
1002
1003         @param reactor: The Twisted reactor.
1004         """
1005         for name, method in self._reactorMethods.iteritems():
1006             setattr(reactor, name, method)
1007         self._reactorMethods = {}
1008
1009     def _installObserver(self):
1010         self._observer = _logObserver
1011         self._observer._add()
1012
1013     def _removeObserver(self):
1014         self._observer._remove()
1015
1016     def flushLoggedErrors(self, *errorTypes):
1017         """
1018         Remove stored errors received from the log.
1019
1020         C{TestCase} stores each error logged during the run of the test and
1021         reports them as errors during the cleanup phase (after C{tearDown}).
1022
1023         @param *errorTypes: If unspecifed, flush all errors. Otherwise, only
1024         flush errors that match the given types.
1025
1026         @return: A list of failures that have been removed.
1027         """
1028         return self._observer.flushErrors(*errorTypes)
1029
1030
1031     def flushWarnings(self, offendingFunctions=None):
1032         """
1033         Remove stored warnings from the list of captured warnings and return
1034         them.
1035
1036         @param offendingFunctions: If C{None}, all warnings issued during the
1037             currently running test will be flushed.  Otherwise, only warnings
1038             which I{point} to a function included in this list will be flushed.
1039             All warnings include a filename and source line number; if these
1040             parts of a warning point to a source line which is part of a
1041             function, then the warning I{points} to that function.
1042         @type offendingFunctions: L{NoneType} or L{list} of functions or methods.
1043
1044         @raise ValueError: If C{offendingFunctions} is not C{None} and includes
1045             an object which is not a L{FunctionType} or L{MethodType} instance.
1046
1047         @return: A C{list}, each element of which is a C{dict} giving
1048             information about one warning which was flushed by this call.  The
1049             keys of each C{dict} are:
1050
1051                 - C{'message'}: The string which was passed as the I{message}
1052                   parameter to L{warnings.warn}.
1053
1054                 - C{'category'}: The warning subclass which was passed as the
1055                   I{category} parameter to L{warnings.warn}.
1056
1057                 - C{'filename'}: The name of the file containing the definition
1058                   of the code object which was C{stacklevel} frames above the
1059                   call to L{warnings.warn}, where C{stacklevel} is the value of
1060                   the C{stacklevel} parameter passed to L{warnings.warn}.
1061
1062                 - C{'lineno'}: The source line associated with the active
1063                   instruction of the code object object which was C{stacklevel}
1064                   frames above the call to L{warnings.warn}, where
1065                   C{stacklevel} is the value of the C{stacklevel} parameter
1066                   passed to L{warnings.warn}.
1067         """
1068         if offendingFunctions is None:
1069             toFlush = self._warnings[:]
1070             self._warnings[:] = []
1071         else:
1072             toFlush = []
1073             for aWarning in self._warnings:
1074                 for aFunction in offendingFunctions:
1075                     if not isinstance(aFunction, (
1076                             types.FunctionType, types.MethodType)):
1077                         raise ValueError("%r is not a function or method" % (
1078                                 aFunction,))
1079
1080                     # inspect.getabsfile(aFunction) sometimes returns a
1081                     # filename which disagrees with the filename the warning
1082                     # system generates.  This seems to be because a
1083                     # function's code object doesn't deal with source files
1084                     # being renamed.  inspect.getabsfile(module) seems
1085                     # better (or at least agrees with the warning system
1086                     # more often), and does some normalization for us which
1087                     # is desirable.  inspect.getmodule() is attractive, but
1088                     # somewhat broken in Python 2.3.  See Python bug 4845.
1089                     aModule = sys.modules[aFunction.__module__]
1090                     filename = inspect.getabsfile(aModule)
1091
1092                     if filename != os.path.normcase(aWarning.filename):
1093                         continue
1094                     lineStarts = list(_findlinestarts(aFunction.func_code))
1095                     first = lineStarts[0][1]
1096                     last = lineStarts[-1][1]
1097                     if not (first <= aWarning.lineno <= last):
1098                         continue
1099                     # The warning points to this function, flush it and move on
1100                     # to the next warning.
1101                     toFlush.append(aWarning)
1102                     break
1103             # Remove everything which is being flushed.
1104             map(self._warnings.remove, toFlush)
1105
1106         return [
1107             {'message': w.message, 'category': w.category,
1108              'filename': w.filename, 'lineno': w.lineno}
1109             for w in toFlush]
1110
1111
1112     def addCleanup(self, f, *args, **kwargs):
1113         """
1114         Add the given function to a list of functions to be called after the
1115         test has run, but before C{tearDown}.
1116
1117         Functions will be run in reverse order of being added. This helps
1118         ensure that tear down complements set up.
1119
1120         The function C{f} may return a Deferred. If so, C{TestCase} will wait
1121         until the Deferred has fired before proceeding to the next function.
1122         """
1123         self._cleanups.append((f, args, kwargs))
1124
1125
1126     def callDeprecated(self, version, f, *args, **kwargs):
1127         """
1128         Call a function that was deprecated at a specific version.
1129
1130         @param version: The version that the function was deprecated in.
1131         @param f: The deprecated function to call.
1132         @return: Whatever the function returns.
1133         """
1134         result = f(*args, **kwargs)
1135         warningsShown = self.flushWarnings([self.callDeprecated])
1136
1137         if len(warningsShown) == 0:
1138             self.fail('%r is not deprecated.' % (f,))
1139
1140         observedWarning = warningsShown[0]['message']
1141         expectedWarning = getDeprecationWarningString(f, version)
1142         self.assertEqual(expectedWarning, observedWarning)
1143
1144         return result
1145
1146
1147     def _runCleanups(self):
1148         """
1149         Run the cleanups added with L{addCleanup} in order.
1150
1151         @return: A C{Deferred} that fires when all cleanups are run.
1152         """
1153         def _makeFunction(f, args, kwargs):
1154             return lambda: f(*args, **kwargs)
1155         callables = []
1156         while len(self._cleanups) > 0:
1157             f, args, kwargs = self._cleanups.pop()
1158             callables.append(_makeFunction(f, args, kwargs))
1159         return util._runSequentially(callables)
1160
1161
1162     def patch(self, obj, attribute, value):
1163         """
1164         Monkey patch an object for the duration of the test.
1165
1166         The monkey patch will be reverted at the end of the test using the
1167         L{addCleanup} mechanism.
1168
1169         The L{MonkeyPatcher} is returned so that users can restore and
1170         re-apply the monkey patch within their tests.
1171
1172         @param obj: The object to monkey patch.
1173         @param attribute: The name of the attribute to change.
1174         @param value: The value to set the attribute to.
1175         @return: A L{monkey.MonkeyPatcher} object.
1176         """
1177         monkeyPatch = monkey.MonkeyPatcher((obj, attribute, value))
1178         monkeyPatch.patch()
1179         self.addCleanup(monkeyPatch.restore)
1180         return monkeyPatch
1181
1182
1183     def runTest(self):
1184         """
1185         If no C{methodName} argument is passed to the constructor, L{run} will
1186         treat this method as the thing with the actual test inside.
1187         """
1188
1189
1190     def run(self, result):
1191         """
1192         Run the test case, storing the results in C{result}.
1193
1194         First runs C{setUp} on self, then runs the test method (defined in the
1195         constructor), then runs C{tearDown}. Any of these may return
1196         L{Deferred}s. After they complete, does some reactor cleanup.
1197
1198         @param result: A L{TestResult} object.
1199         """
1200         log.msg("--> %s <--" % (self.id()))
1201         from twisted.internet import reactor
1202         new_result = itrial.IReporter(result, None)
1203         if new_result is None:
1204             result = PyUnitResultAdapter(result)
1205         else:
1206             result = new_result
1207         self._timedOut = False
1208         if self._shared and self not in self.__class__._instances:
1209             self.__class__._instances.add(self)
1210         result.startTest(self)
1211         if self.getSkip(): # don't run test methods that are marked as .skip
1212             result.addSkip(self, self.getSkip())
1213             result.stopTest(self)
1214             return
1215         self._installObserver()
1216
1217         # All the code inside runThunk will be run such that warnings emitted
1218         # by it will be collected and retrievable by flushWarnings.
1219         def runThunk():
1220             self._passed = False
1221             first = False
1222             if self._shared:
1223                 first = self._isFirst()
1224                 self.__class__._instancesRun.add(self)
1225             self._deprecateReactor(reactor)
1226             try:
1227                 if first:
1228                     d = self.deferSetUpClass(result)
1229                 else:
1230                     d = self.deferSetUp(None, result)
1231                 try:
1232                     self._wait(d)
1233                 finally:
1234                     self._cleanUp(result)
1235                     if self._shared and self._isLast():
1236                         self._initInstances()
1237                         self._classCleanUp(result)
1238                     if not self._shared:
1239                         self._classCleanUp(result)
1240             finally:
1241                 self._undeprecateReactor(reactor)
1242
1243         self._warnings = []
1244         _collectWarnings(self._warnings.append, runThunk)
1245
1246         # Any collected warnings which the test method didn't flush get
1247         # re-emitted so they'll be logged or show up on stdout or whatever.
1248         for w in self.flushWarnings():
1249             try:
1250                 warnings.warn_explicit(**w)
1251             except:
1252                 result.addError(self, failure.Failure())
1253
1254         result.stopTest(self)
1255
1256
1257     def _getReason(self, f):
1258         if len(f.value.args) > 0:
1259             reason = f.value.args[0]
1260         else:
1261             warnings.warn(("Do not raise unittest.SkipTest with no "
1262                            "arguments! Give a reason for skipping tests!"),
1263                           stacklevel=2)
1264             reason = f
1265         return reason
1266
1267     def getSkip(self):
1268         """
1269         Return the skip reason set on this test, if any is set. Checks on the
1270         instance first, then the class, then the module, then packages. As
1271         soon as it finds something with a C{skip} attribute, returns that.
1272         Returns C{None} if it cannot find anything. See L{TestCase} docstring
1273         for more details.
1274         """
1275         return util.acquireAttribute(self._parents, 'skip', None)
1276
1277     def getTodo(self):
1278         """
1279         Return a L{Todo} object if the test is marked todo. Checks on the
1280         instance first, then the class, then the module, then packages. As
1281         soon as it finds something with a C{todo} attribute, returns that.
1282         Returns C{None} if it cannot find anything. See L{TestCase} docstring
1283         for more details.
1284         """
1285         todo = util.acquireAttribute(self._parents, 'todo', None)
1286         if todo is None:
1287             return None
1288         return makeTodo(todo)
1289
1290     def getTimeout(self):
1291         """
1292         Returns the timeout value set on this test. Checks on the instance
1293         first, then the class, then the module, then packages. As soon as it
1294         finds something with a C{timeout} attribute, returns that. Returns
1295         L{util.DEFAULT_TIMEOUT_DURATION} if it cannot find anything. See
1296         L{TestCase} docstring for more details.
1297         """
1298         timeout =  util.acquireAttribute(self._parents, 'timeout',
1299                                          util.DEFAULT_TIMEOUT_DURATION)
1300         try:
1301             return float(timeout)
1302         except (ValueError, TypeError):
1303             # XXX -- this is here because sometimes people will have methods
1304             # called 'timeout', or set timeout to 'orange', or something
1305             # Particularly, test_news.NewsTestCase and ReactorCoreTestCase
1306             # both do this.
1307             warnings.warn("'timeout' attribute needs to be a number.",
1308                           category=DeprecationWarning)
1309             return util.DEFAULT_TIMEOUT_DURATION
1310
1311     def getSuppress(self):
1312         """
1313         Returns any warning suppressions set for this test. Checks on the
1314         instance first, then the class, then the module, then packages. As
1315         soon as it finds something with a C{suppress} attribute, returns that.
1316         Returns any empty list (i.e. suppress no warnings) if it cannot find
1317         anything. See L{TestCase} docstring for more details.
1318         """
1319         return util.acquireAttribute(self._parents, 'suppress', [])
1320
1321
1322     def visit(self, visitor):
1323         """
1324         Visit this test case. Call C{visitor} with C{self} as a parameter.
1325
1326         Deprecated in Twisted 8.0.
1327
1328         @param visitor: A callable which expects a single parameter: a test
1329         case.
1330
1331         @return: None
1332         """
1333         warnings.warn("Test visitors deprecated in Twisted 8.0",
1334                       category=DeprecationWarning)
1335         visitor(self)
1336
1337
1338     def mktemp(self):
1339         """Returns a unique name that may be used as either a temporary
1340         directory or filename.
1341
1342         @note: you must call os.mkdir on the value returned from this
1343                method if you wish to use it as a directory!
1344         """
1345         MAX_FILENAME = 32 # some platforms limit lengths of filenames
1346         base = os.path.join(self.__class__.__module__[:MAX_FILENAME],
1347                             self.__class__.__name__[:MAX_FILENAME],
1348                             self._testMethodName[:MAX_FILENAME])
1349         if not os.path.exists(base):
1350             os.makedirs(base)
1351         dirname = tempfile.mkdtemp('', '', base)
1352         return os.path.join(dirname, 'temp')
1353
1354     def _wait(self, d, running=_wait_is_running):
1355         """Take a Deferred that only ever callbacks. Block until it happens.
1356         """
1357         from twisted.internet import reactor
1358         if running:
1359             raise RuntimeError("_wait is not reentrant")
1360
1361         results = []
1362         def append(any):
1363             if results is not None:
1364                 results.append(any)
1365         def crash(ign):
1366             if results is not None:
1367                 reactor.crash()
1368         crash = utils.suppressWarnings(
1369             crash, util.suppress(message=r'reactor\.crash cannot be used.*',
1370                                  category=DeprecationWarning))
1371         def stop():
1372             reactor.crash()
1373         stop = utils.suppressWarnings(
1374             stop, util.suppress(message=r'reactor\.crash cannot be used.*',
1375                                 category=DeprecationWarning))
1376
1377         running.append(None)
1378         try:
1379             d.addBoth(append)
1380             if results:
1381                 # d might have already been fired, in which case append is
1382                 # called synchronously. Avoid any reactor stuff.
1383                 return
1384             d.addBoth(crash)
1385             reactor.stop = stop
1386             try:
1387                 reactor.run()
1388             finally:
1389                 del reactor.stop
1390
1391             # If the reactor was crashed elsewhere due to a timeout, hopefully
1392             # that crasher also reported an error. Just return.
1393             # _timedOut is most likely to be set when d has fired but hasn't
1394             # completed its callback chain (see self._run)
1395             if results or self._timedOut: #defined in run() and _run()
1396                 return
1397
1398             # If the timeout didn't happen, and we didn't get a result or
1399             # a failure, then the user probably aborted the test, so let's
1400             # just raise KeyboardInterrupt.
1401
1402             # FIXME: imagine this:
1403             # web/test/test_webclient.py:
1404             # exc = self.assertRaises(error.Error, wait, method(url))
1405             #
1406             # wait() will raise KeyboardInterrupt, and assertRaises will
1407             # swallow it. Therefore, wait() raising KeyboardInterrupt is
1408             # insufficient to stop trial. A suggested solution is to have
1409             # this code set a "stop trial" flag, or otherwise notify trial
1410             # that it should really try to stop as soon as possible.
1411             raise KeyboardInterrupt()
1412         finally:
1413             results = None
1414             running.pop()
1415
1416
1417 class UnsupportedTrialFeature(Exception):
1418     """A feature of twisted.trial was used that pyunit cannot support."""
1419
1420
1421 class PyUnitResultAdapter(object):
1422     """
1423     Wrap a C{TestResult} from the standard library's C{unittest} so that it
1424     supports the extended result types from Trial, and also supports
1425     L{twisted.python.failure.Failure}s being passed to L{addError} and
1426     L{addFailure}.
1427     """
1428
1429     def __init__(self, original):
1430         """
1431         @param original: A C{TestResult} instance from C{unittest}.
1432         """
1433         self.original = original
1434
1435     def _exc_info(self, err):
1436         if isinstance(err, failure.Failure):
1437             # Unwrap the Failure into a exc_info tuple.
1438             err = (err.type, err.value, err.getTracebackObject())
1439         return err
1440
1441     def startTest(self, method):
1442         self.original.startTest(method)
1443
1444     def stopTest(self, method):
1445         self.original.stopTest(method)
1446
1447     def addFailure(self, test, fail):
1448         self.original.addFailure(test, self._exc_info(fail))
1449
1450     def addError(self, test, error):
1451         self.original.addError(test, self._exc_info(error))
1452
1453     def _unsupported(self, test, feature, info):
1454         self.original.addFailure(
1455             test,
1456             (UnsupportedTrialFeature,
1457              UnsupportedTrialFeature(feature, info),
1458              None))
1459
1460     def addSkip(self, test, reason):
1461         """
1462         Report the skip as a failure.
1463         """
1464         self._unsupported(test, 'skip', reason)
1465
1466     def addUnexpectedSuccess(self, test, todo):
1467         """
1468         Report the unexpected success as a failure.
1469         """
1470         self._unsupported(test, 'unexpected success', todo)
1471
1472     def addExpectedFailure(self, test, error):
1473         """
1474         Report the expected failure (i.e. todo) as a failure.
1475         """
1476         self._unsupported(test, 'expected failure', error)
1477
1478     def addSuccess(self, test):
1479         self.original.addSuccess(test)
1480
1481     def upDownError(self, method, error, warn, printStatus):
1482         pass
1483
1484
1485
1486 def suiteVisit(suite, visitor):
1487     """
1488     Visit each test in C{suite} with C{visitor}.
1489
1490     Deprecated in Twisted 8.0.
1491
1492     @param visitor: A callable which takes a single argument, the L{TestCase}
1493     instance to visit.
1494     @return: None
1495     """
1496     warnings.warn("Test visitors deprecated in Twisted 8.0",
1497                   category=DeprecationWarning)
1498     for case in suite._tests:
1499         visit = getattr(case, 'visit', None)
1500         if visit is not None:
1501             visit(visitor)
1502         elif isinstance(case, pyunit.TestCase):
1503             case = itrial.ITestCase(case)
1504             case.visit(visitor)
1505         elif isinstance(case, pyunit.TestSuite):
1506             suiteVisit(case, visitor)
1507         else:
1508             case.visit(visitor)
1509
1510
1511
1512 class TestSuite(pyunit.TestSuite):
1513     """
1514     Extend the standard library's C{TestSuite} with support for the visitor
1515     pattern and a consistently overrideable C{run} method.
1516     """
1517
1518     visit = suiteVisit
1519
1520     def __call__(self, result):
1521         return self.run(result)
1522
1523
1524     def run(self, result):
1525         """
1526         Call C{run} on every member of the suite.
1527         """
1528         # we implement this because Python 2.3 unittest defines this code
1529         # in __call__, whereas 2.4 defines the code in run.
1530         for test in self._tests:
1531             if result.shouldStop:
1532                 break
1533             test(result)
1534         return result
1535
1536
1537
1538 class TestDecorator(components.proxyForInterface(itrial.ITestCase,
1539                                                  "_originalTest")):
1540     """
1541     Decorator for test cases.
1542
1543     @param _originalTest: The wrapped instance of test.
1544     @type _originalTest: A provider of L{itrial.ITestCase}
1545     """
1546
1547     implements(itrial.ITestCase)
1548
1549
1550     def __call__(self, result):
1551         """
1552         Run the unit test.
1553
1554         @param result: A TestResult object.
1555         """
1556         return self.run(result)
1557
1558
1559     def run(self, result):
1560         """
1561         Run the unit test.
1562
1563         @param result: A TestResult object.
1564         """
1565         return self._originalTest.run(
1566             reporter._AdaptedReporter(result, self.__class__))
1567
1568
1569
1570 def _clearSuite(suite):
1571     """
1572     Clear all tests from C{suite}.
1573
1574     This messes with the internals of C{suite}. In particular, it assumes that
1575     the suite keeps all of its tests in a list in an instance variable called
1576     C{_tests}.
1577     """
1578     suite._tests = []
1579
1580
1581 def decorate(test, decorator):
1582     """
1583     Decorate all test cases in C{test} with C{decorator}.
1584
1585     C{test} can be a test case or a test suite. If it is a test suite, then the
1586     structure of the suite is preserved.
1587
1588     L{decorate} tries to preserve the class of the test suites it finds, but
1589     assumes the presence of the C{_tests} attribute on the suite.
1590
1591     @param test: The C{TestCase} or C{TestSuite} to decorate.
1592
1593     @param decorator: A unary callable used to decorate C{TestCase}s.
1594
1595     @return: A decorated C{TestCase} or a C{TestSuite} containing decorated
1596         C{TestCase}s.
1597     """
1598
1599     try:
1600         tests = iter(test)
1601     except TypeError:
1602         return decorator(test)
1603
1604     # At this point, we know that 'test' is a test suite.
1605     _clearSuite(test)
1606
1607     for case in tests:
1608         test.addTest(decorate(case, decorator))
1609     return test
1610
1611
1612
1613 class _PyUnitTestCaseAdapter(TestDecorator):
1614     """
1615     Adapt from pyunit.TestCase to ITestCase.
1616     """
1617
1618
1619     def visit(self, visitor):
1620         """
1621         Deprecated in Twisted 8.0.
1622         """
1623         warnings.warn("Test visitors deprecated in Twisted 8.0",
1624                       category=DeprecationWarning)
1625         visitor(self)
1626
1627
1628
1629 class _BrokenIDTestCaseAdapter(_PyUnitTestCaseAdapter):
1630     """
1631     Adapter for pyunit-style C{TestCase} subclasses that have undesirable id()
1632     methods. That is L{pyunit.FunctionTestCase} and L{pyunit.DocTestCase}.
1633     """
1634
1635     def id(self):
1636         """
1637         Return the fully-qualified Python name of the doctest.
1638         """
1639         testID = self._originalTest.shortDescription()
1640         if testID is not None:
1641             return testID
1642         return self._originalTest.id()
1643
1644
1645
1646 class _ForceGarbageCollectionDecorator(TestDecorator):
1647     """
1648     Forces garbage collection to be run before and after the test. Any errors
1649     logged during the post-test collection are added to the test result as
1650     errors.
1651     """
1652
1653     def run(self, result):
1654         gc.collect()
1655         TestDecorator.run(self, result)
1656         _logObserver._add()
1657         gc.collect()
1658         for error in _logObserver.getErrors():
1659             result.addError(self, error)
1660         _logObserver.flushErrors()
1661         _logObserver._remove()
1662
1663
1664 components.registerAdapter(
1665     _PyUnitTestCaseAdapter, pyunit.TestCase, itrial.ITestCase)
1666
1667
1668 components.registerAdapter(
1669     _BrokenIDTestCaseAdapter, pyunit.FunctionTestCase, itrial.ITestCase)
1670
1671
1672 _docTestCase = getattr(doctest, 'DocTestCase', None)
1673 if _docTestCase:
1674     components.registerAdapter(
1675         _BrokenIDTestCaseAdapter, _docTestCase, itrial.ITestCase)
1676
1677
1678 def _iterateTests(testSuiteOrCase):
1679     """
1680     Iterate through all of the test cases in C{testSuiteOrCase}.
1681     """
1682     try:
1683         suite = iter(testSuiteOrCase)
1684     except TypeError:
1685         yield testSuiteOrCase
1686     else:
1687         for test in suite:
1688             for subtest in _iterateTests(test):
1689                 yield subtest
1690
1691
1692
1693 # Support for Python 2.3
1694 try:
1695     iter(pyunit.TestSuite())
1696 except TypeError:
1697     # Python 2.3's TestSuite doesn't support iteration. Let's monkey patch it!
1698     def __iter__(self):
1699         return iter(self._tests)
1700     pyunit.TestSuite.__iter__ = __iter__
1701
1702
1703
1704 class _SubTestCase(TestCase):
1705     def __init__(self):
1706         TestCase.__init__(self, 'run')
1707
1708 _inst = _SubTestCase()
1709
1710 def _deprecate(name):
1711     """
1712     Internal method used to deprecate top-level assertions. Do not use this.
1713     """
1714     def _(*args, **kwargs):
1715         warnings.warn("unittest.%s is deprecated.  Instead use the %r "
1716                       "method on unittest.TestCase" % (name, name),
1717                       stacklevel=2, category=DeprecationWarning)
1718         return getattr(_inst, name)(*args, **kwargs)
1719     return _
1720
1721
1722 _assertions = ['fail', 'failUnlessEqual', 'failIfEqual', 'failIfEquals',
1723                'failUnless', 'failUnlessIdentical', 'failUnlessIn',
1724                'failIfIdentical', 'failIfIn', 'failIf',
1725                'failUnlessAlmostEqual', 'failIfAlmostEqual',
1726                'failUnlessRaises', 'assertApproximates',
1727                'assertFailure', 'failUnlessSubstring', 'failIfSubstring',
1728                'assertAlmostEqual', 'assertAlmostEquals',
1729                'assertNotAlmostEqual', 'assertNotAlmostEquals', 'assertEqual',
1730                'assertEquals', 'assertNotEqual', 'assertNotEquals',
1731                'assertRaises', 'assert_', 'assertIdentical',
1732                'assertNotIdentical', 'assertIn', 'assertNotIn',
1733                'failUnlessFailure', 'assertSubstring', 'assertNotSubstring']
1734
1735
1736 for methodName in _assertions:
1737     globals()[methodName] = _deprecate(methodName)
1738
1739
1740 __all__ = ['TestCase', 'wait', 'FailTest', 'SkipTest']
Note: See TracBrowser for help on using the browser.