github.com/tiagovtristao/plz@v13.4.0+incompatible/tools/please_pex/unittest.py (about)

     1  import os
     2  import sys
     3  import unittest
     4  from importlib import import_module
     5  
     6  
     7  def list_classes(suite):
     8      for test in suite:
     9          if isinstance(test, unittest.suite.TestSuite):
    10              for cls, name in list_classes(test):
    11                  yield cls, name
    12          else:
    13              yield test, test.__class__.__module__ + '.' + test.id()
    14  
    15  
    16  def get_suite(test_names, raise_on_empty=False):
    17      """
    18      Get the test suite to run the test
    19  
    20      :param test_names: Name of the tests to be filtered
    21      :param raise_on_empty: raise Exception if result filtered is empty
    22  
    23      :return: unittest.suite.TestSuite
    24      """
    25      suite = unittest.TestSuite(unittest.defaultTestLoader.loadTestsFromModule(module)
    26                                 for module in import_tests())
    27      # Filter to test name only, this ensures the extra flags does not get swallowed
    28      test_names = list(filter(lambda x: not x.startswith('-'), test_names))
    29  
    30      # filter results if test_names is not empty
    31      if test_names:
    32          new_suite = unittest.suite.TestSuite()
    33          for name in test_names:
    34              new_suite.addTests(cls for cls, class_name in list_classes(suite)
    35                                 if name in class_name)
    36          if raise_on_empty and suite.countTestCases() == 0:
    37              raise Exception('No matching tests found')
    38  
    39          return new_suite
    40  
    41      return suite
    42  
    43  
    44  def import_tests():
    45      """Yields the set of test modules, from file if necessary."""
    46      # We have files available locally, but there may (likely) also be python files in the same
    47      # Python package within the pex. We can't just import them because the parent package exists
    48      # in only one of those places (this is similar to importing generated code from plz-out/gen).
    49      for filename in TEST_NAMES:
    50          pkg_name, _ = os.path.splitext(filename.replace('/', '.'))
    51          try:
    52              yield import_module(pkg_name)
    53          except ImportError:
    54              with open(filename, 'r') as f:
    55                  if PY_VERSION < 3:
    56                      mod = imp.load_module(pkg_name, f, filename, ('.py', 'r', imp.PY_SOURCE))
    57                  else:
    58                      mod = machinery.SourceFileLoader(pkg_name, filename).load_module()
    59  
    60                  # Have to set the attribute on the parent module too otherwise some things
    61                  # can't find it.
    62                  parent, _, mod_name = pkg_name.rpartition('.')
    63                  if parent and parent in sys.modules:
    64                      setattr(sys.modules[parent], mod_name, mod)
    65                  yield mod
    66  
    67  
    68  def run_tests(test_names):
    69      """Runs tests using unittest, returns the number of failures."""
    70      # N.B. import must be deferred until we have set up import paths.
    71      import xmlrunner
    72      suite = get_suite(test_names, raise_on_empty=True)
    73  
    74      runner = xmlrunner.XMLTestRunner(output='test.results', outsuffix='')
    75      results = runner.run(suite)
    76      return len(results.errors) + len(results.failures)