def tests_from_suite(suite, options, dlevel=1, dlayer=zope.testrunner.layer.UnitTests): """Returns a sequence of (test, layer_name) The tree of suites is recursively visited, with the most specific layer taking precedence. So if a TestCase with a layer of 'foo' is contained in a TestSuite with a layer of 'bar', the test case would be returned with 'foo' as the layer. Tests are also filtered out based on the test level and test selection filters stored in the options. """ level = getattr(suite, 'level', dlevel) layer = getattr(suite, 'layer', dlayer) if not isinstance(layer, six.string_types): layer = name_from_layer(layer) if isinstance(suite, unittest.TestSuite): for possible_suite in suite: for r in tests_from_suite(possible_suite, options, level, layer): yield r elif isinstance(suite, StartUpFailure): yield (suite, None) else: if options.only: accept = build_filtering_func(options.test) if accept(str(suite)) and level == options.only: yield (suite, layer) elif level <= options.at_level: accept = build_filtering_func(options.test) if accept(str(suite)): yield (suite, layer)
def find_tests(options, found_suites=None): """Creates a dictionary mapping layer name to a suite of tests to be run in that layer. Passing a list of suites using the found_suites parameter will cause that list of suites to be used instead of attempting to load them from the filesystem. This is useful for unit testing the test runner. """ remove_stale_bytecode(options) suites = {} dupe_ids = set() test_accept = build_filtering_func(options.test) module_accept = build_filtering_func(options.module) if found_suites is None: found_suites = find_suites(options, accept=module_accept) for suite in found_suites: for test, layer_name in tests_from_suite(suite, options, accept=test_accept, duplicated_test_ids=dupe_ids): if dupe_ids: # If there are any duplicated test IDs, we stop trying to # load tests; we'll raise an error later on with all the # duplicates in it. continue suite = suites.get(layer_name) if not suite: suite = suites[layer_name] = unittest.TestSuite() suite.addTest(test) if dupe_ids: message_lines = ['Duplicate test IDs found:'] + sorted(dupe_ids) message = '\n '.join(message_lines) raise DuplicateTestIDError(message) return suites
def find_tests(options, found_suites=None): """Creates a dictionary mapping layer name to a suite of tests to be run in that layer. Passing a list of suites using the found_suites parameter will cause that list of suites to be used instead of attempting to load them from the filesystem. This is useful for unit testing the test runner. """ remove_stale_bytecode(options) suites = {} test_accept = build_filtering_func(options.test) module_accept = build_filtering_func(options.module) if found_suites is None: found_suites = find_suites(options, accept=module_accept) for suite in found_suites: for test, layer_name in tests_from_suite(suite, options, accept=test_accept): suite = suites.get(layer_name) if not suite: suite = suites[layer_name] = unittest.TestSuite() suite.addTest(test) return suites
def tests_from_suite(suite, options, dlevel=1, dlayer=zope.testrunner.layer.UnitTests): """Returns a sequence of (test, layer_name) The tree of suites is recursively visited, with the most specific layer taking precedence. So if a TestCase with a layer of 'foo' is contained in a TestSuite with a layer of 'bar', the test case would be returned with 'foo' as the layer. Tests are also filtered out based on the test level and test selection filters stored in the options. """ level = getattr(suite, 'level', dlevel) layer = getattr(suite, 'layer', dlayer) if not isinstance(layer, six.string_types): layer = name_from_layer(layer) if isinstance(suite, unittest.TestSuite): for possible_suite in suite: for r in tests_from_suite(possible_suite, options, level, layer): yield r elif isinstance(suite, StartUpFailure): yield (suite, None) else: if level <= options.at_level: accept = build_filtering_func(options.test) if accept(str(suite)): yield (suite, layer)
def find_suites(options): for fpath, package in find_test_files(options): for (prefix, prefix_package) in options.prefix: if fpath.startswith(prefix) and package == prefix_package: # strip prefix, strip .py suffix and convert separator to dots noprefix = fpath[len(prefix):] noext = strip_py_ext(options, noprefix) assert noext is not None module_name = noext.replace(os.path.sep, '.') if package: module_name = package + '.' + module_name accept = build_filtering_func(options.module) if not accept(module_name): continue try: module = import_name(module_name) except KeyboardInterrupt: raise except: exc_info = sys.exc_info() if not options.post_mortem: # Skip a couple of frames exc_info = exc_info[:2] + (exc_info[2].tb_next.tb_next,) suite = StartUpFailure( options, module_name, exc_info) else: try: if hasattr(module, options.suite_name): suite = getattr(module, options.suite_name)() else: suite = unittest.defaultTestLoader.loadTestsFromModule(module) if suite.countTestCases() == 0: raise TypeError( "Module %s does not define any tests" % module_name) if isinstance(suite, unittest.TestSuite): check_suite(suite, module_name) else: raise TypeError( "Invalid test_suite, %r, in %s" % (suite, module_name) ) except KeyboardInterrupt: raise except: exc_info = sys.exc_info() if not options.post_mortem: # Suppress traceback exc_info = exc_info[:2] + (None,) suite = StartUpFailure( options, module_name, exc_info) yield suite break
def find_suites(options): for fpath, package in find_test_files(options): for (prefix, prefix_package) in options.prefix: if fpath.startswith(prefix) and package == prefix_package: # strip prefix, strip .py suffix and convert separator to dots noprefix = fpath[len(prefix):] noext = strip_py_ext(options, noprefix) assert noext is not None module_name = noext.replace(os.path.sep, '.') if package: module_name = package + '.' + module_name accept = build_filtering_func(options.module) if not accept(module_name): continue try: module = import_name(module_name) except KeyboardInterrupt: raise except: exc_info = sys.exc_info() if not options.post_mortem: # Skip a couple of frames exc_info = exc_info[:2] + (exc_info[2].tb_next.tb_next,) suite = StartUpFailure( options, module_name, exc_info) else: try: if hasattr(module, options.suite_name): suite = getattr(module, options.suite_name)() else: suite = unittest.defaultTestLoader.loadTestsFromModule(module) if suite.countTestCases() == 0: raise TypeError( "Module %s does not define any tests" % module_name) if isinstance(suite, unittest.TestSuite): check_suite(suite, module_name) else: raise TypeError( "Invalid test_suite, %r, in %s" % (suite, module_name) ) except KeyboardInterrupt: raise except: exc_info = sys.exc_info() if not options.post_mortem: # Suppress traceback exc_info = exc_info[:2] + (None,) suite = StartUpFailure( options, module_name, exc_info) yield suite break
def find_tests(options, found_suites=None): """Creates a dictionary mapping layer name to a suite of tests to be run in that layer. Passing a list of suites using the found_suites parameter will cause that list of suites to be used instead of attempting to load them from the filesystem. This is useful for unit testing the test runner. """ remove_stale_bytecode(options) suites = {} test_accept = build_filtering_func(options.test) module_accept = build_filtering_func(options.module) if found_suites is None: found_suites = find_suites(options, accept=module_accept) for suite in found_suites: for test, layer_name in tests_from_suite(suite, options, accept=test_accept): suite = suites.get(layer_name) if not suite: suite = suites[layer_name] = unittest.TestSuite() suite.addTest(test) return suites
def find_tests(options, found_suites=None): """Creates a dictionary mapping layer name to a suite of tests to be run in that layer. Passing a list of suites using the found_suites parameter will cause that list of suites to be used instead of attempting to load them from the filesystem. This is useful for unit testing the test runner. """ remove_stale_bytecode(options) suites = {} dupe_ids = set() test_accept = build_filtering_func(options.test) module_accept = build_filtering_func(options.module) if found_suites is None: found_suites = find_suites(options, accept=module_accept) for suite in found_suites: for test, layer_name in tests_from_suite(suite, options, accept=test_accept, duplicated_test_ids=dupe_ids): if dupe_ids: # If there are any duplicated test IDs, we stop trying to # load tests; we'll raise an error later on with all the # duplicates in it. continue suite = suites.get(layer_name) if not suite: suite = suites[layer_name] = unittest.TestSuite() suite.addTest(test) if dupe_ids: message_lines = ['Duplicate test IDs found:'] + sorted(dupe_ids) message = '\n '.join(message_lines) raise DuplicateTestIDError(message) return suites
def test_accept_and_reject_same(self): accept = filter.build_filtering_func(['yy', '!yy']) self.assertFalse(accept('test_xx')) self.assertFalse(accept('test_yy')) self.assertFalse(accept('test_zz'))
def test_accept_and_reject_overlap(self): accept = filter.build_filtering_func(['!test_', 'yy']) self.assertFalse(accept('test_xx')) self.assertFalse(accept('test_yy')) self.assertFalse(accept('test_zz'))
def test_reject_several_patterns(self): accept = filter.build_filtering_func(['!xx', '!zz']) self.assertFalse(accept('test_xx')) self.assertTrue(accept('test_yy')) self.assertFalse(accept('test_zz'))
def test_reject_one_pattern(self): accept = filter.build_filtering_func(['!xx']) self.assertFalse(accept('test_xx')) self.assertTrue(accept('test_yy')) self.assertTrue(accept('test_zz'))
def test_select_specific_pattern(self): accept = filter.build_filtering_func(['xx']) self.assertTrue(accept('test_xx')) self.assertFalse(accept('test_yy')) self.assertFalse(accept('test_zz'))
def test_match_all_filter(self): accept = filter.build_filtering_func(['.']) self.assertTrue(accept('test_xx')) self.assertTrue(accept('test_yy')) self.assertTrue(accept('test_zz'))
def test_no_filters(self): accept = filter.build_filtering_func([]) self.assertFalse(accept('test_xx')) self.assertFalse(accept('test_yy')) self.assertFalse(accept('test_zz'))