Home | History | Annotate | Download | only in common
      1 # Copyright 2013 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """Utilities for dealing with the python unittest module."""
      6 
      7 import fnmatch
      8 import sys
      9 import unittest
     10 
     11 
     12 class _TextTestResult(unittest._TextTestResult):
     13   """A test result class that can print formatted text results to a stream.
     14 
     15   Results printed in conformance with gtest output format, like:
     16   [ RUN        ] autofill.AutofillTest.testAutofillInvalid: "test desc."
     17   [         OK ] autofill.AutofillTest.testAutofillInvalid
     18   [ RUN        ] autofill.AutofillTest.testFillProfile: "test desc."
     19   [         OK ] autofill.AutofillTest.testFillProfile
     20   [ RUN        ] autofill.AutofillTest.testFillProfileCrazyCharacters: "Test."
     21   [         OK ] autofill.AutofillTest.testFillProfileCrazyCharacters
     22   """
     23   def __init__(self, stream, descriptions, verbosity):
     24     unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
     25     self._fails = set()
     26 
     27   def _GetTestURI(self, test):
     28     return '%s.%s.%s' % (test.__class__.__module__,
     29                          test.__class__.__name__,
     30                          test._testMethodName)
     31 
     32   def getDescription(self, test):
     33     return '%s: "%s"' % (self._GetTestURI(test), test.shortDescription())
     34 
     35   def startTest(self, test):
     36     unittest.TestResult.startTest(self, test)
     37     self.stream.writeln('[ RUN        ] %s' % self.getDescription(test))
     38 
     39   def addSuccess(self, test):
     40     unittest.TestResult.addSuccess(self, test)
     41     self.stream.writeln('[         OK ] %s' % self._GetTestURI(test))
     42 
     43   def addError(self, test, err):
     44     unittest.TestResult.addError(self, test, err)
     45     self.stream.writeln('[      ERROR ] %s' % self._GetTestURI(test))
     46     self._fails.add(self._GetTestURI(test))
     47 
     48   def addFailure(self, test, err):
     49     unittest.TestResult.addFailure(self, test, err)
     50     self.stream.writeln('[     FAILED ] %s' % self._GetTestURI(test))
     51     self._fails.add(self._GetTestURI(test))
     52 
     53   def getRetestFilter(self):
     54     return ':'.join(self._fails)
     55 
     56 
     57 class TextTestRunner(unittest.TextTestRunner):
     58   """Test Runner for displaying test results in textual format.
     59 
     60   Results are displayed in conformance with google test output.
     61   """
     62 
     63   def __init__(self, verbosity=1):
     64     unittest.TextTestRunner.__init__(self, stream=sys.stderr,
     65                                      verbosity=verbosity)
     66 
     67   def _makeResult(self):
     68     return _TextTestResult(self.stream, self.descriptions, self.verbosity)
     69 
     70 
     71 def GetTestsFromSuite(suite):
     72   """Returns all the tests from a given test suite."""
     73   tests = []
     74   for x in suite:
     75     if isinstance(x, unittest.TestSuite):
     76       tests += GetTestsFromSuite(x)
     77     else:
     78       tests += [x]
     79   return tests
     80 
     81 
     82 def GetTestNamesFromSuite(suite):
     83   """Returns a list of every test name in the given suite."""
     84   return map(lambda x: GetTestName(x), GetTestsFromSuite(suite))
     85 
     86 
     87 def GetTestName(test):
     88   """Gets the test name of the given unittest test."""
     89   return '.'.join([test.__class__.__module__,
     90                    test.__class__.__name__,
     91                    test._testMethodName])
     92 
     93 
     94 def FilterTestSuite(suite, gtest_filter):
     95   """Returns a new filtered tests suite based on the given gtest filter.
     96 
     97   See http://code.google.com/p/googletest/wiki/AdvancedGuide
     98   for gtest_filter specification.
     99   """
    100   return unittest.TestSuite(FilterTests(GetTestsFromSuite(suite), gtest_filter))
    101 
    102 
    103 def FilterTests(all_tests, gtest_filter):
    104   """Filter a list of tests based on the given gtest filter.
    105 
    106   Args:
    107     all_tests: List of tests (unittest.TestSuite)
    108     gtest_filter: Filter to apply.
    109 
    110   Returns:
    111     Filtered subset of the given list of tests.
    112   """
    113   test_names = [GetTestName(test) for test in all_tests]
    114   filtered_names = FilterTestNames(test_names, gtest_filter)
    115   return [test for test in all_tests if GetTestName(test) in filtered_names]
    116 
    117 
    118 def FilterTestNames(all_tests, gtest_filter):
    119   """Filter a list of test names based on the given gtest filter.
    120 
    121   See http://code.google.com/p/googletest/wiki/AdvancedGuide
    122   for gtest_filter specification.
    123 
    124   Args:
    125     all_tests: List of test names.
    126     gtest_filter: Filter to apply.
    127 
    128   Returns:
    129     Filtered subset of the given list of test names.
    130   """
    131   pattern_groups = gtest_filter.split('-')
    132   positive_patterns = pattern_groups[0].split(':')
    133   negative_patterns = None
    134   if len(pattern_groups) > 1:
    135     negative_patterns = pattern_groups[1].split(':')
    136 
    137   tests = []
    138   for test in all_tests:
    139     # Test name must by matched by one positive pattern.
    140     for pattern in positive_patterns:
    141       if fnmatch.fnmatch(test, pattern):
    142         break
    143     else:
    144       continue
    145     # Test name must not be matched by any negative patterns.
    146     for pattern in negative_patterns or []:
    147       if fnmatch.fnmatch(test, pattern):
    148         break
    149     else:
    150       tests += [test]
    151   return tests
    152