1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Utilities for dealing with the python unittest module."""
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import fnmatch
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import unittest
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class _TextTestResult(unittest._TextTestResult):
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """A test result class that can print formatted text results to a stream.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Results printed in conformance with gtest output format, like:
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [ RUN        ] autofill.AutofillTest.testAutofillInvalid: "test desc."
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [         OK ] autofill.AutofillTest.testAutofillInvalid
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [ RUN        ] autofill.AutofillTest.testFillProfile: "test desc."
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [         OK ] autofill.AutofillTest.testFillProfile
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [ RUN        ] autofill.AutofillTest.testFillProfileCrazyCharacters: "Test."
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [         OK ] autofill.AutofillTest.testFillProfileCrazyCharacters
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, stream, descriptions, verbosity):
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._fails = set()
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GetTestURI(self, test):
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return '%s.%s.%s' % (test.__class__.__module__,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         test.__class__.__name__,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         test._testMethodName)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def getDescription(self, test):
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return '%s: "%s"' % (self._GetTestURI(test), test.shortDescription())
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def startTest(self, test):
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unittest.TestResult.startTest(self, test)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.stream.writeln('[ RUN        ] %s' % self.getDescription(test))
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def addSuccess(self, test):
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unittest.TestResult.addSuccess(self, test)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.stream.writeln('[         OK ] %s' % self._GetTestURI(test))
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def addError(self, test, err):
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unittest.TestResult.addError(self, test, err)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.stream.writeln('[      ERROR ] %s' % self._GetTestURI(test))
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._fails.add(self._GetTestURI(test))
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def addFailure(self, test, err):
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unittest.TestResult.addFailure(self, test, err)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.stream.writeln('[     FAILED ] %s' % self._GetTestURI(test))
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._fails.add(self._GetTestURI(test))
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def getRetestFilter(self):
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ':'.join(self._fails)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TextTestRunner(unittest.TextTestRunner):
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Test Runner for displaying test results in textual format.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Results are displayed in conformance with google test output.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, verbosity=1):
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unittest.TextTestRunner.__init__(self, stream=sys.stderr,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     verbosity=verbosity)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _makeResult(self):
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return _TextTestResult(self.stream, self.descriptions, self.verbosity)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetTestsFromSuite(suite):
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Returns all the tests from a given test suite."""
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tests = []
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for x in suite:
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if isinstance(x, unittest.TestSuite):
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tests += GetTestsFromSuite(x)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tests += [x]
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return tests
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetTestNamesFromSuite(suite):
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Returns a list of every test name in the given suite."""
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return map(lambda x: GetTestName(x), GetTestsFromSuite(suite))
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetTestName(test):
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Gets the test name of the given unittest test."""
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return '.'.join([test.__class__.__module__,
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   test.__class__.__name__,
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   test._testMethodName])
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def FilterTestSuite(suite, gtest_filter):
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Returns a new filtered tests suite based on the given gtest filter.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  See http://code.google.com/p/googletest/wiki/AdvancedGuide
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for gtest_filter specification.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return unittest.TestSuite(FilterTests(GetTestsFromSuite(suite), gtest_filter))
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def FilterTests(all_tests, gtest_filter):
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  """Filter a list of tests based on the given gtest filter.
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Args:
107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    all_tests: List of tests (unittest.TestSuite)
108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    gtest_filter: Filter to apply.
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Returns:
111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Filtered subset of the given list of tests.
112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  """
113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  test_names = [GetTestName(test) for test in all_tests]
114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  filtered_names = FilterTestNames(test_names, gtest_filter)
115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return [test for test in all_tests if GetTestName(test) in filtered_names]
116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)def FilterTestNames(all_tests, gtest_filter):
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  """Filter a list of test names based on the given gtest filter.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  See http://code.google.com/p/googletest/wiki/AdvancedGuide
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for gtest_filter specification.
123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Args:
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    all_tests: List of test names.
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    gtest_filter: Filter to apply.
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Returns:
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    Filtered subset of the given list of test names.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pattern_groups = gtest_filter.split('-')
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  positive_patterns = pattern_groups[0].split(':')
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  negative_patterns = None
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if len(pattern_groups) > 1:
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    negative_patterns = pattern_groups[1].split(':')
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tests = []
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for test in all_tests:
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Test name must by matched by one positive pattern.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for pattern in positive_patterns:
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if fnmatch.fnmatch(test, pattern):
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Test name must not be matched by any negative patterns.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for pattern in negative_patterns or []:
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if fnmatch.fnmatch(test, pattern):
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tests += [test]
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return tests
152