github.phpd.cn/thought-machine/please@v12.2.0+incompatible/tools/please_pex/unittest.py (about)

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