Commits

Michael Foord committed e585c7e

Adding afterSummaryReport and beforeSummaryReport events
Renaming StopTestEvent to TestReport

Comments (0)

Files changed (4)

 * ``afterSetUp``
 * ``beforeTearDown``
 * ``onTestFail``
+* ``createReport``
 * ``stopTest``
 * ``stopTestRun``
 * ``message``
+* ``beforeSummaryReport``
+* ``afterSummaryReport``
 
 Event objects all have a `message` method for writing to the default output stream whilst honouring the verbosity of the test runner. See `New messaging API that honours verbosity`_.
 
 This event cannot be handled. If this event sets ``exc_info`` to None then the exception is suppressed and the test becomes a pass. After this event is completed ``event.exc_info`` is reraised - so the event can *modify* the exception by modifying ``exc_info``.
 
 
-stopTest
---------
+createReport & stopTest
+------------------------
 
-This event is fired when a test execution is completed. It includes a great deal of information about the test and could be used to completely replace test reporting, making the test result potentially obsolete. It will be used by the junit-xml plugin to generate the xml reports describing the test run.
+These events are fired when a test execution is completed. They include a great deal of information about the test result and can be used to modify the report of a test (like custom outcomes) or to provide additional reporting (like junit compatible xml for example).
 
-If there are errors during a tearDown or clean up functions then this event may be fired several times for a test. For each call the ``stage`` will be different, although there could be several errors during clean up functions.
+Modifying the way a test result is reported should be done in the ``createReport`` event so that reporting plugins hooked into ``stopTest`` all see the same report.
+
+If there are errors during a tearDown or clean up functions then these event may be fired several times for a single test. For each call the ``stage`` will be different, although there could be several errors during clean up functions.
 
 Attributes on the ``StopTestEvent`` are:
 
 * ``timeTaken`` - total time for test execution from setUp to clean up functions
 * ``stage`` - one of setUp, call, tearDown, cleanUp, or None for success
 * ``outcome`` - one of passed, failed, error, skipped, unexpectedSuccess, expectedFailure
+* ``standardOutcome`` - normally the same as ``outcome``, but guaranteed to always be one of the standard set of outcomes even if a custom outcome is used - tools that can only handle the standard set of outcomes should use this attribute instead of ``outcome``
+* ``shortResult`` - the single letter used for reporting the test result during the run (typically '.', 's', etc)
+* ``longResult`` - longer text for reporting results during a run ("ok", "skipped", etc)
+* ``description`` - description of the test (produced by calling ``result.getDescription(test)`` or ``str(test)`` if the result has no ``getDescription`` method)
+* ``traceback`` - the traceback that will be output in the event of a test fail or error (produced by calling ``test.formatTraceback(exc_info)`` or ``util.formatTraceback(exc_info)`` if the test has no ``formatTraceback`` method) or None
+* ``metadata`` - a dictionary that can be used for attaching arbitrary metadata to test reports, for use by custom reporting tools
 
 The outcomes all correspond to an attribute that will be set to True or False depending on outcome:
 
 
 In addition there is a ``skipReason`` that will be None unless the test was skipped, in which case it will be a string containing the reason.
 
-This event cannot be handled. 
+This event cannot be handled.
 
 
 stopTestRun
 Handler functions may modify ``event.message`` and ``event.verbosity`` and the modified values will be used.
 
 
+beforeSummaryReport & afterSummaryReport
+----------------------------------------
+
+These two events fire before and after the summary of the test run is output. It can be used by plugins to output additional information about the test run. Both these events use the same ``ReportEvent`` objects. Attributes available are:
+
+* ``runner`` - the test runner
+* ``result`` - the test result
+
+Note that if you want to output information before the test failure / error messages are output you can use the ``stopTestRun`` event.
+
+
 New messaging API that honours verbosity
 ========================================
 

unittest2/case.py

 
 from unittest2.compatibility import wraps
 from unittest2.events import (
-    hooks, TestFailEvent, StartTestEvent, StopTestEvent,
+    hooks, TestFailEvent, StartTestEvent, TestReport,
     AfterSetUpEvent, BeforeTearDownEvent
 )
 
     # Attribute used by cleanups for timing tests
     _startTime = 0
 
-    def __init__(self, methodName='runTest'):
+    def __init__(self, methodName='runTest', test):
         """Create an instance of the class that will use the named test
            method when executed. Raises a ValueError if the instance does
            not have a method with the specified name.
         if outcome in ('failed', 'error'):
             traceback = self.formatTraceback(exc_info)
         
-        event = StopTestEvent(self, result, stopTime, timeTaken, outcome,
+        event = TestReport(self, result, stopTime, timeTaken, outcome,
                               exc_info, stage, traceback)
 
         # first event allows customisation of the report

unittest2/events.py

     'LoadFromModuleEvent',
     'LoadFromTestCaseEvent',
     'MessageEvent',
+    'RunnerCreatedEvent',
     'StartTestRunEvent',
     'StopTestRunEvent',
     'StartTestEvent',
     'StopTestEvent',
     'TestFailEvent',
+    'ReportEvent',
+    'BeforeTearDownEvent',
+    'AfterSetUpEvent',
     # for plugins
     'hooks',
     'addOption',
     'expectedFailure': ("expected failure", 'x'),
     'unexpectedSuccess': ('unexpected success', 'u'),
 }
-class StopTestEvent(_Event):
+class TestReport(_Event):
     def __init__(self, test, result, stopTime, timeTaken, outcome, exc_info,
                  stage, traceback):
         _Event.__init__(self)
         self.test = None
         self.exc_info = None
         self.result = None
-        
+
+class ReportEvent(_Event):
+    def __init__(self, runner, result):
+        self.runner = runner
+        self.result = result
+    
 
 class PluginsLoadedEvent(_Event):
     loadedPlugins = loadedPlugins
     stopTest = _EventHook()
     stopTestRun = _EventHook()
     message = _EventHook()
+    
+    beforeSummaryReport = _EventHook()
+    afterSummaryReport = _EventHook()
 
 
 class Register(type):

unittest2/runner.py

 from unittest2 import result
 from unittest2.events import (
     hooks, StartTestRunEvent, StopTestRunEvent,
-    RunnerCreatedEvent, MessageEvent
+    RunnerCreatedEvent, MessageEvent, ReportEvent
 )
 
 try:
             else:
                 result.printErrors()
 
+        reportEvent = ReportEvent(self, result)
+        hooks.beforeSummaryReport(reportEvent)
         if hasattr(result, 'separator2'):
             self.message(result.separator2, (0, 1, 2))
             self.message('\n')
         if infos:
             self.message(" (%s)" % (", ".join(infos),), (0, 1, 2))
         self.message("\n")
+        hooks.afterSummaryReport(reportEvent)
         return result