1ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch# Copyright 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)# found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)"""Utilities for dealing with the python unittest module."""
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import fnmatch
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import sys
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)import unittest
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class _TextTestResult(unittest._TextTestResult):
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """A test result class that can print formatted text results to a stream.
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Results printed in conformance with gtest output format, like:
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  [ RUN        ] autofill.AutofillTest.testAutofillInvalid: "test desc."
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  [         OK ] autofill.AutofillTest.testAutofillInvalid
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  [ RUN        ] autofill.AutofillTest.testFillProfile: "test desc."
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  [         OK ] autofill.AutofillTest.testFillProfile
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  [ RUN        ] autofill.AutofillTest.testFillProfileCrazyCharacters: "Test."
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  [         OK ] autofill.AutofillTest.testFillProfileCrazyCharacters
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  def __init__(self, stream, descriptions, verbosity):
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    unittest._TextTestResult.__init__(self, stream, descriptions, verbosity)
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    self._fails = set()
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  def _GetTestURI(self, test):
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return '%s.%s.%s' % (test.__class__.__module__,
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         test.__class__.__name__,
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         test._testMethodName)
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  def getDescription(self, test):
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return '%s: "%s"' % (self._GetTestURI(test), test.shortDescription())
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  def startTest(self, test):
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    unittest.TestResult.startTest(self, test)
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    self.stream.writeln('[ RUN        ] %s' % self.getDescription(test))
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  def addSuccess(self, test):
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    unittest.TestResult.addSuccess(self, test)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    self.stream.writeln('[         OK ] %s' % self._GetTestURI(test))
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  def addError(self, test, err):
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    unittest.TestResult.addError(self, test, err)
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    self.stream.writeln('[      ERROR ] %s' % self._GetTestURI(test))
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    self._fails.add(self._GetTestURI(test))
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  def addFailure(self, test, err):
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    unittest.TestResult.addFailure(self, test, err)
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    self.stream.writeln('[     FAILED ] %s' % self._GetTestURI(test))
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    self._fails.add(self._GetTestURI(test))
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  def getRetestFilter(self):
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return ':'.join(self._fails)
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class TextTestRunner(unittest.TextTestRunner):
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """Test Runner for displaying test results in textual format.
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Results are displayed in conformance with google test output.
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  def __init__(self, verbosity=1):
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    unittest.TextTestRunner.__init__(self, stream=sys.stderr,
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                     verbosity=verbosity)
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  def _makeResult(self):
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return _TextTestResult(self.stream, self.descriptions, self.verbosity)
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)def GetTestsFromSuite(suite):
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """Returns all the tests from a given test suite."""
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  tests = []
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for x in suite:
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if isinstance(x, unittest.TestSuite):
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      tests += GetTestsFromSuite(x)
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    else:
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      tests += [x]
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return tests
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)def GetTestNamesFromSuite(suite):
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """Returns a list of every test name in the given suite."""
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return map(lambda x: GetTestName(x), GetTestsFromSuite(suite))
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)def GetTestName(test):
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """Gets the test name of the given unittest test."""
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return '.'.join([test.__class__.__module__,
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                   test.__class__.__name__,
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                   test._testMethodName])
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)def FilterTestSuite(suite, gtest_filter):
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """Returns a new filtered tests suite based on the given gtest filter.
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  See http://code.google.com/p/googletest/wiki/AdvancedGuide
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for gtest_filter specification.
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return unittest.TestSuite(FilterTests(GetTestsFromSuite(suite), gtest_filter))
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)def FilterTests(all_tests, gtest_filter):
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """Returns a filtered list of tests based on the given gtest filter.
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  See http://code.google.com/p/googletest/wiki/AdvancedGuide
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for gtest_filter specification.
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  """
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  pattern_groups = gtest_filter.split('-')
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  positive_patterns = pattern_groups[0].split(':')
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  negative_patterns = None
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if len(pattern_groups) > 1:
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    negative_patterns = pattern_groups[1].split(':')
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  tests = []
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for test in all_tests:
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    test_name = GetTestName(test)
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    # Test name must by matched by one positive pattern.
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for pattern in positive_patterns:
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if fnmatch.fnmatch(test_name, pattern):
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    else:
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    # Test name must not be matched by any negative patterns.
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for pattern in negative_patterns or []:
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if fnmatch.fnmatch(test_name, pattern):
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        break
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    else:
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      tests += [test]
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return tests
131