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)