Ejemplo n.º 1
0
    def build_suite(self, test_labels=None, extra_tests=None, **kwargs):
        test_labels = test_labels or ['.']
        extra_tests = extra_tests or []
        self.test_loader.testNamePatterns = self.test_name_patterns

        discover_kwargs = {}
        if self.pattern is not None:
            discover_kwargs['pattern'] = self.pattern
        if self.top_level is not None:
            discover_kwargs['top_level_dir'] = self.top_level

        all_tests = []
        for label in test_labels:
            tests = self.load_tests_for_label(label, discover_kwargs)
            all_tests.extend(iter_test_cases(tests))

        all_tests.extend(iter_test_cases(extra_tests))

        if self.tags or self.exclude_tags:
            if self.tags:
                self.log(
                    'Including test tag(s): %s.' %
                    ', '.join(sorted(self.tags)),
                    level=logging.DEBUG,
                )
            if self.exclude_tags:
                self.log(
                    'Excluding test tag(s): %s.' %
                    ', '.join(sorted(self.exclude_tags)),
                    level=logging.DEBUG,
                )
            all_tests = filter_tests_by_tags(all_tests, self.tags,
                                             self.exclude_tags)

        # Put the failures detected at load time first for quicker feedback.
        # _FailedTest objects include things like test modules that couldn't be
        # found or that couldn't be loaded due to syntax errors.
        test_types = (unittest.loader._FailedTest, *self.reorder_by)
        all_tests = list(reorder_tests(all_tests, test_types, self.reverse))
        self.log('Found %d test(s).' % len(all_tests))
        suite = self.test_suite(all_tests)

        if self.parallel > 1:
            parallel_suite = self.parallel_test_suite(
                suite,
                self.parallel,
                self.failfast,
                self.buffer,
            )

            # Since tests are distributed across processes on a per-TestCase
            # basis, there's no need for more processes than TestCases.
            parallel_units = len(parallel_suite.subsuites)
            self.parallel = min(self.parallel, parallel_units)

            # If there's only one TestCase, parallelization isn't needed.
            if self.parallel > 1:
                suite = parallel_suite

        return suite
Ejemplo n.º 2
0
    def build_suite(self, test_labels=None, extra_tests=None, **kwargs):
        test_labels = test_labels or ['.']
        extra_tests = extra_tests or []
        self.test_loader.testNamePatterns = self.test_name_patterns

        discover_kwargs = {}
        if self.pattern is not None:
            discover_kwargs['pattern'] = self.pattern
        if self.top_level is not None:
            discover_kwargs['top_level_dir'] = self.top_level

        all_tests = []
        for label in test_labels:
            label_as_path = os.path.abspath(label)
            tests = None

            # if a module, or "module.ClassName[.method_name]", just run those
            if not os.path.exists(label_as_path):
                tests = self.test_loader.loadTestsFromName(label)

            # Try discovery if "label" is a package or directory.
            if not (tests and tests.countTestCases()) and is_discoverable(label):
                kwargs = discover_kwargs.copy()
                if os.path.isdir(label_as_path) and not self.top_level:
                    kwargs['top_level_dir'] = find_top_level(label_as_path)

                tests = self.test_loader.discover(start_dir=label, **kwargs)

                # Make unittest forget the top-level dir it calculated from this
                # run, to support running tests from two different top-levels.
                self.test_loader._top_level_dir = None

            all_tests.extend(iter_test_cases(tests))

        all_tests.extend(iter_test_cases(extra_tests))

        if self.tags or self.exclude_tags:
            if self.verbosity >= 2:
                if self.tags:
                    print('Including test tag(s): %s.' % ', '.join(sorted(self.tags)))
                if self.exclude_tags:
                    print('Excluding test tag(s): %s.' % ', '.join(sorted(self.exclude_tags)))
            all_tests = filter_tests_by_tags(all_tests, self.tags, self.exclude_tags)

        all_tests = reorder_tests(all_tests, self.reorder_by, self.reverse)
        suite = self.test_suite(all_tests)

        if self.parallel > 1:
            parallel_suite = self.parallel_test_suite(suite, self.parallel, self.failfast)

            # Since tests are distributed across processes on a per-TestCase
            # basis, there's no need for more processes than TestCases.
            parallel_units = len(parallel_suite.subsuites)
            self.parallel = min(self.parallel, parallel_units)

            # If there's only one TestCase, parallelization isn't needed.
            if self.parallel > 1:
                suite = parallel_suite

        return suite
Ejemplo n.º 3
0
def reorder_suite(suite, classes, reverse=False):
    """
    Reorder a test suite by test type, removing any duplicates.

    `classes` is a sequence of types

    All tests of type classes[0] are placed first, then tests of type
    classes[1], etc. Tests with no match in classes are placed last.

    If `reverse` is True, sort tests within classes in opposite order but
    don't reverse test classes.
    """
    bins = [OrderedSet() for i in range(len(classes) + 1)]
    *class_bins, last_bin = bins

    for test in iter_test_cases(suite):
        for test_bin, test_class in zip(class_bins, classes):
            if isinstance(test, test_class):
                break
        else:
            test_bin = last_bin
        test_bin.add(test)

    if reverse:
        bins = (reversed(tests) for tests in bins)
    suite_class = type(suite)
    return suite_class(itertools.chain(*bins))
Ejemplo n.º 4
0
def partition_suite_by_case(suite):
    """Partition a test suite by test case, preserving the order of tests."""
    suite_class = type(suite)
    all_tests = iter_test_cases(suite)
    return [
        suite_class(tests) for _, tests in itertools.groupby(all_tests, type)
    ]
Ejemplo n.º 5
0
    def test_reorder_tests_reverse_with_duplicates(self):
        class Tests1(unittest.TestCase):
            def test1(self):
                pass

        class Tests2(unittest.TestCase):
            def test2(self):
                pass

            def test3(self):
                pass

        suite = self.build_test_suite((Tests1, Tests2))
        subsuite = list(suite)[0]
        suite.addTest(subsuite)
        tests = list(iter_test_cases(suite))
        self.assertTestNames(tests, expected=[
            'Tests1.test1', 'Tests2.test2', 'Tests2.test3', 'Tests1.test1',
        ])
        reordered_tests = reorder_tests(tests, classes=[])
        self.assertTestNames(reordered_tests, expected=[
            'Tests1.test1', 'Tests2.test2', 'Tests2.test3',
        ])
        reordered_tests = reorder_tests(tests, classes=[], reverse=True)
        self.assertTestNames(reordered_tests, expected=[
            'Tests2.test3', 'Tests2.test2', 'Tests1.test1',
        ])
Ejemplo n.º 6
0
 def test_iter_test_cases_mixed_test_suite_classes(self):
     suite = self.make_test_suite(suite=MySuite())
     child_suite = list(suite)[0]
     self.assertNotIsInstance(child_suite, MySuite)
     tests = list(iter_test_cases(suite))
     self.assertEqual(len(tests), 4)
     self.assertNotIsInstance(tests[0], unittest.TestSuite)
Ejemplo n.º 7
0
 def test_iter_test_cases_string_input(self):
     msg = (
         "Test 'a' must be a test case or test suite not string (was found "
         "in 'abc')."
     )
     with self.assertRaisesMessage(TypeError, msg):
         list(iter_test_cases("abc"))
Ejemplo n.º 8
0
 def test_iter_test_cases_custom_test_suite_class(self):
     suite = self.make_test_suite(suite_class=MySuite)
     tests = iter_test_cases(suite)
     self.assertTestNames(tests,
                          expected=[
                              'Tests1.test1',
                              'Tests1.test2',
                              'Tests2.test1',
                              'Tests2.test2',
                          ])
Ejemplo n.º 9
0
 def test_iter_test_cases_basic(self):
     suite = self.make_test_suite()
     tests = iter_test_cases(suite)
     self.assertTestNames(tests,
                          expected=[
                              'Tests1.test1',
                              'Tests1.test2',
                              'Tests2.test1',
                              'Tests2.test2',
                          ])
Ejemplo n.º 10
0
def partition_suite_by_case(suite):
    """Partition a test suite by test case, preserving the order of tests."""
    subsuites = []
    suite_class = type(suite)
    tests = iter_test_cases(suite)
    for test_type, test_group in itertools.groupby(tests, type):
        subsuite = suite_class(test_group)
        subsuites.append(subsuite)

    return subsuites
Ejemplo n.º 11
0
 def _get_databases(self, suite):
     databases = {}
     for test in iter_test_cases(suite):
         test_databases = getattr(test, 'databases', None)
         if test_databases == '__all__':
             test_databases = connections
         if test_databases:
             serialized_rollback = getattr(test, 'serialized_rollback',
                                           False)
             databases.update(
                 (alias, serialized_rollback or databases.get(alias, False))
                 for alias in test_databases)
     return databases
Ejemplo n.º 12
0
    def test_iter_test_cases_iterable_of_tests(self):
        class Tests(unittest.TestCase):
            def test1(self):
                pass

            def test2(self):
                pass

        tests = list(unittest.defaultTestLoader.loadTestsFromTestCase(Tests))
        actual_tests = iter_test_cases(tests)
        self.assertTestNames(actual_tests, expected=[
            'Tests.test1', 'Tests.test2',
        ])
Ejemplo n.º 13
0
def filter_tests_by_tags(suite, tags, exclude_tags):
    suite_class = type(suite)
    filtered_suite = suite_class()

    for test in iter_test_cases(suite):
        test_tags = set(getattr(test, 'tags', set()))
        test_fn_name = getattr(test, '_testMethodName', str(test))
        test_fn = getattr(test, test_fn_name, test)
        test_fn_tags = set(getattr(test_fn, 'tags', set()))
        all_tags = test_tags.union(test_fn_tags)
        matched_tags = all_tags.intersection(tags)
        if (matched_tags
                or not tags) and not all_tags.intersection(exclude_tags):
            filtered_suite.addTest(test)

    return filtered_suite
Ejemplo n.º 14
0
def partition_suite_by_type(suite, classes, bins, reverse=False):
    """
    Partition a test suite by test type. Also prevent duplicated tests.

    classes is a sequence of types
    bins is a sequence of TestSuites, one more than classes
    reverse changes the ordering of tests within bins

    Tests of type classes[i] are added to bins[i],
    tests with no match found in classes are place in bins[-1]
    """
    for test in iter_test_cases(suite, reverse=reverse):
        for i in range(len(classes)):
            if isinstance(test, classes[i]):
                bins[i].add(test)
                break
        else:
            bins[-1].add(test)
Ejemplo n.º 15
0
    def build_suite(self, test_labels=None, extra_tests=None, **kwargs):
        test_labels = test_labels or ['.']
        extra_tests = extra_tests or []
        self.test_loader.testNamePatterns = self.test_name_patterns

        discover_kwargs = {}
        if self.pattern is not None:
            discover_kwargs['pattern'] = self.pattern
        if self.top_level is not None:
            discover_kwargs['top_level_dir'] = self.top_level

        all_tests = []
        for label in test_labels:
            kwargs = discover_kwargs.copy()
            tests = None

            label_as_path = os.path.abspath(label)

            # if a module, or "module.ClassName[.method_name]", just run those
            if not os.path.exists(label_as_path):
                tests = self.test_loader.loadTestsFromName(label)
            elif os.path.isdir(label_as_path) and not self.top_level:
                # Try to be a bit smarter than unittest about finding the
                # default top-level for a given directory path, to avoid
                # breaking relative imports. (Unittest's default is to set
                # top-level equal to the path, which means relative imports
                # will result in "Attempted relative import in non-package.").

                # We'd be happy to skip this and require dotted module paths
                # (which don't cause this problem) instead of file paths (which
                # do), but in the case of a directory in the cwd, which would
                # be equally valid if considered as a top-level module or as a
                # directory path, unittest unfortunately prefers the latter.

                top_level = label_as_path
                while True:
                    init_py = os.path.join(top_level, '__init__.py')
                    if not os.path.exists(init_py):
                        break
                    try_next = os.path.dirname(top_level)
                    if try_next == top_level:
                        # __init__.py all the way down? give up.
                        break
                    top_level = try_next
                kwargs['top_level_dir'] = top_level

            if not (tests
                    and tests.countTestCases()) and is_discoverable(label):
                # Try discovery if path is a package or directory
                tests = self.test_loader.discover(start_dir=label, **kwargs)

                # Make unittest forget the top-level dir it calculated from this
                # run, to support running tests from two different top-levels.
                self.test_loader._top_level_dir = None

            all_tests.extend(iter_test_cases(tests))

        all_tests.extend(iter_test_cases(extra_tests))

        if self.tags or self.exclude_tags:
            if self.verbosity >= 2:
                if self.tags:
                    print('Including test tag(s): %s.' %
                          ', '.join(sorted(self.tags)))
                if self.exclude_tags:
                    print('Excluding test tag(s): %s.' %
                          ', '.join(sorted(self.exclude_tags)))
            all_tests = filter_tests_by_tags(all_tests, self.tags,
                                             self.exclude_tags)

        all_tests = reorder_tests(all_tests, self.reorder_by, self.reverse)
        suite = self.test_suite(all_tests)

        if self.parallel > 1:
            parallel_suite = self.parallel_test_suite(suite, self.parallel,
                                                      self.failfast)

            # Since tests are distributed across processes on a per-TestCase
            # basis, there's no need for more processes than TestCases.
            parallel_units = len(parallel_suite.subsuites)
            self.parallel = min(self.parallel, parallel_units)

            # If there's only one TestCase, parallelization isn't needed.
            if self.parallel > 1:
                suite = parallel_suite

        return suite
Ejemplo n.º 16
0
def filter_tests_by_tags(suite, tags, exclude_tags):
    suite_class = type(suite)
    return suite_class(test for test in iter_test_cases(suite)
                       if test_match_tags(test, tags, exclude_tags))
Ejemplo n.º 17
0
 def test_reverse(self):
     suite = self.make_test_suite()
     tests = iter_test_cases(suite, reverse=True)
     self.assertTestNames(tests, expected=[
         'Tests2.test2', 'Tests2.test1', 'Tests1.test2', 'Tests1.test1',
     ])
Ejemplo n.º 18
0
    def build_suite(self, test_labels=None, extra_tests=None, **kwargs):
        if extra_tests is not None:
            warnings.warn(
                'The extra_tests argument is deprecated.',
                RemovedInDjango50Warning,
                stacklevel=2,
            )
        test_labels = test_labels or ['.']
        extra_tests = extra_tests or []

        discover_kwargs = {}
        if self.pattern is not None:
            discover_kwargs['pattern'] = self.pattern
        if self.top_level is not None:
            discover_kwargs['top_level_dir'] = self.top_level
        self.setup_shuffler()

        all_tests = []
        for label in test_labels:
            tests = self.load_tests_for_label(label, discover_kwargs)
            all_tests.extend(iter_test_cases(tests))

        all_tests.extend(iter_test_cases(extra_tests))

        if self.tags or self.exclude_tags:
            if self.tags:
                self.log(
                    'Including test tag(s): %s.' %
                    ', '.join(sorted(self.tags)),
                    level=logging.DEBUG,
                )
            if self.exclude_tags:
                self.log(
                    'Excluding test tag(s): %s.' %
                    ', '.join(sorted(self.exclude_tags)),
                    level=logging.DEBUG,
                )
            all_tests = filter_tests_by_tags(all_tests, self.tags,
                                             self.exclude_tags)

        # Put the failures detected at load time first for quicker feedback.
        # _FailedTest objects include things like test modules that couldn't be
        # found or that couldn't be loaded due to syntax errors.
        test_types = (unittest.loader._FailedTest, *self.reorder_by)
        all_tests = list(
            reorder_tests(
                all_tests,
                test_types,
                shuffler=self._shuffler,
                reverse=self.reverse,
            ))
        self.log('Found %d test(s).' % len(all_tests))
        suite = self.test_suite(all_tests)

        if self.parallel > 1:
            subsuites = partition_suite_by_case(suite)
            # Since tests are distributed across processes on a per-TestCase
            # basis, there's no need for more processes than TestCases.
            processes = min(self.parallel, len(subsuites))
            if processes > 1:
                suite = self.parallel_test_suite(
                    subsuites,
                    processes,
                    self.failfast,
                    self.buffer,
                )
        return suite
Ejemplo n.º 19
0
 def make_tests(self):
     """Return an iterable of tests."""
     suite = self.make_test_suite()
     tests = list(iter_test_cases(suite))
     return tests