~jameinel/subunit/only-genuine-failures

« back to all changes in this revision

Viewing changes to python/subunit/test_results.py

  • Committer: Jonathan Lange
  • Date: 2010-08-05 12:29:20 UTC
  • mfrom: (131.1.3 move-ls)
  • Revision ID: jml@canonical.com-20100805122920-t6z0viif1x08yu0e
Move the bulk of subunit-ls into an importable Python module.

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
#  license at the users choice. A copy of both licenses are available in the
7
7
#  project source as Apache-2.0 and BSD. You may not use this file except in
8
8
#  compliance with one of these two licences.
9
 
#  
 
9
#
10
10
#  Unless required by applicable law or agreed to in writing, software
11
11
#  distributed under these licenses is distributed on an "AS IS" BASIS, WITHOUT
12
12
#  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
21
21
import iso8601
22
22
import testtools
23
23
 
24
 
import subunit
25
 
 
26
24
 
27
25
# NOT a TestResult, because we are implementing the interface, not inheriting
28
26
# it.
29
27
class TestResultDecorator(object):
30
28
    """General pass-through decorator.
31
29
 
32
 
    This provides a base that other TestResults can inherit from to 
33
 
    gain basic forwarding functionality. It also takes care of 
 
30
    This provides a base that other TestResults can inherit from to
 
31
    gain basic forwarding functionality. It also takes care of
34
32
    handling the case where the target doesn't support newer methods
35
33
    or features by degrading them.
36
34
    """
201
199
    """A pyunit TestResult interface implementation which filters tests.
202
200
 
203
201
    Tests that pass the filter are handed on to another TestResult instance
204
 
    for further processing/reporting. To obtain the filtered results, 
 
202
    for further processing/reporting. To obtain the filtered results,
205
203
    the other instance must be interrogated.
206
204
 
207
205
    :ivar result: The result that tests are passed to after filtering.
208
 
    :ivar filter_predicate: The callback run to decide whether to pass 
 
206
    :ivar filter_predicate: The callback run to decide whether to pass
209
207
        a result.
210
208
    """
211
209
 
213
211
        filter_success=True, filter_skip=False,
214
212
        filter_predicate=None):
215
213
        """Create a FilterResult object filtering to result.
216
 
        
 
214
 
217
215
        :param filter_error: Filter out errors.
218
216
        :param filter_failure: Filter out failures.
219
217
        :param filter_success: Filter out successful tests.
238
236
        self._current_test_filtered = None
239
237
        # The (new, gone) tags for the current test.
240
238
        self._current_test_tags = None
241
 
        
 
239
 
242
240
    def addError(self, test, err=None, details=None):
243
 
        if (not self._filter_error and 
 
241
        if (not self._filter_error and
244
242
            self.filter_predicate(test, 'error', err, details)):
245
243
            self.decorated.startTest(test)
246
244
            self.decorated.addError(test, err, details=details)
288
286
 
289
287
    def startTest(self, test):
290
288
        """Start a test.
291
 
        
 
289
 
292
290
        Not directly passed to the client, but used for handling of tags
293
291
        correctly.
294
292
        """
295
293
        self._current_test = test
296
294
        self._current_test_filtered = False
297
295
        self._current_test_tags = set(), set()
298
 
    
 
296
 
299
297
    def stopTest(self, test):
300
298
        """Stop a test.
301
 
        
 
299
 
302
300
        Not directly passed to the client, but used for handling of tags
303
301
        correctly.
304
302
        """
316
314
 
317
315
        Adds and removes tags as appropriate. If a test is currently running,
318
316
        tags are not affected for subsequent tests.
319
 
        
 
317
 
320
318
        :param new_tags: Tags to add,
321
319
        :param gone_tags: Tags to remove.
322
320
        """
332
330
        if id.startswith("subunit.RemotedTestCase."):
333
331
            return id[len("subunit.RemotedTestCase."):]
334
332
        return id
 
333
 
 
334
 
 
335
class TestIdPrintingResult(testtools.TestResult):
 
336
 
 
337
    def __init__(self, stream, show_times=False):
 
338
        """Create a FilterResult object outputting to stream."""
 
339
        testtools.TestResult.__init__(self)
 
340
        self._stream = stream
 
341
        self.failed_tests = 0
 
342
        self.__time = 0
 
343
        self.show_times = show_times
 
344
        self._test = None
 
345
        self._test_duration = 0
 
346
 
 
347
    def addError(self, test, err):
 
348
        self.failed_tests += 1
 
349
        self._test = test
 
350
 
 
351
    def addFailure(self, test, err):
 
352
        self.failed_tests += 1
 
353
        self._test = test
 
354
 
 
355
    def addSuccess(self, test):
 
356
        self._test = test
 
357
 
 
358
    def reportTest(self, test, duration):
 
359
        if self.show_times:
 
360
            seconds = duration.seconds
 
361
            seconds += duration.days * 3600 * 24
 
362
            seconds += duration.microseconds / 1000000.0
 
363
            self._stream.write(test.id() + ' %0.3f\n' % seconds)
 
364
        else:
 
365
            self._stream.write(test.id() + '\n')
 
366
 
 
367
    def startTest(self, test):
 
368
        self._start_time = self._time()
 
369
 
 
370
    def stopTest(self, test):
 
371
        test_duration = self._time() - self._start_time
 
372
        self.reportTest(self._test, test_duration)
 
373
 
 
374
    def time(self, time):
 
375
        self.__time = time
 
376
 
 
377
    def _time(self):
 
378
        return self.__time
 
379
 
 
380
    def wasSuccessful(self):
 
381
        "Tells whether or not this result was a success"
 
382
        return self.failed_tests == 0