Ejemplo n.º 1
0
    def loadTestsFromTestCase(self, testCaseClass):
        """
        Responsible for loading test cases that belongs to any test class inheriting from TINCTestCase.
        By default, this uses the unittest loader for loading test cases. In addition to the default behavior,
        if the test case class has 'loadTestsFromTestCase' defined and implemented, this will call out to the testCaseClass
        for custom loading of tests for the test case class.

        If the test case class is decorated with 'skipLoading', this will ignore loading for the particular test case class.

        @param testCaseClass: Class object of the test case for which the loading should be performed.
        @type testCaseClass: TINCTestCase class object

        @param consider_skip_loading: boolean that tells whether or not to consider the annotation tinctest.skipLoading
        @type consider_skip_loading: boolean

        @rtype: TINCTestSuite
        @return: Tests loaded for the test case class wrapped in a TINCTestSuite
        """
        # Set all tests loaded to True at the beginning of loading a test class
        testCaseClass._all_tests_loaded = True

        # If test case class has the annotation @tinctest.skipLoading, just return
        if self.consider_skip_loading and hasattr(testCaseClass, '__tinc_skip_loading__') and \
               testCaseClass.__tinc_skip_loading__:
            # Check class name and source file to see if it is not inherited
            current_class_name = testCaseClass.__name__
            current_file = sys.modules[testCaseClass.__module__].__file__

            if testCaseClass.__tinc_skip_loading_declared_class__ == current_class_name and \
               testCaseClass.__tinc_skip_loading_declared_file__ == current_file:

                tinctest.logger.info(
                    "Skipping test loading for test class %s: %s" %
                    (testCaseClass.__name__,
                     testCaseClass.__tinc_skip_loading_msg__))
                return TINCTestSuite()

        tinctest.logger.debug(
            "Loading tests for test class: %s.%s" %
            (testCaseClass.__module__, testCaseClass.__name__))
        try:
            test_suite = super(TINCTestLoader,
                               self).loadTestsFromTestCase(testCaseClass)
        except Exception, e:
            # This means that the class did not load properly
            # Add a failure test case to our suite
            test_suite = TINCTestSuite()
            test_suite.addTest(
                make_failed_test(
                    None,
                    testCaseClass.__module__ + "." + testCaseClass.__name__,
                    e))
            return test_suite
Ejemplo n.º 2
0
    def loadTestsFromName(self, name, module=None, dryrun=False, expand=True):
        """
        For dynamically generated test methods, loadTestsFromName from unittest.loader will
        raise an error. We handle the case where the test method is not yet generated in this
        implementation of loadTestsFromName.

        @type name: string
        @param name: Name of the test to be loaded. Could be path to a class, module, test method

        @rtype: TINCTestSuite
        @return: The tests loaded for the given name wrapped in a TINCTestSuite
        """
        test_suite = TINCTestSuite()

        # The following block of code is taken from unittest2.loader.loadTestsFromName.
        # It finds the biggest subset from the given name that can be successfully imported.
        parts = name.split('.')
        if module is None:
            parts_copy = parts[:]
            while parts_copy:
                try:
                    m = __import__('.'.join(parts_copy))
                    break
                except ImportError:
                    del parts_copy[-1]
                    if not parts_copy:
                        raise
            parts = parts[1:]

        obj = m

        # We exclude the last part from the name which could potentially be a test method
        # that is not generated yet.
        for part in parts[:-1]:
            parent, obj = obj, getattr(obj, part)

        try:
            parent, obj = obj, getattr(obj, parts[-1])
        except AttributeError, e:
            # This means that the last part is a method which is not yet generated.
            # So we construct an instance of the test class which will dynamically
            # add the test method to its instance.
            #if not issubclass(obj, SQLTestCase):
            #    raise TypeError("don't know how to make test from: %s" % obj)
            try:
                klass = getattr(parent, parts[-2])
                test = klass(parts[-1])
                test_suite.addTest(test)
            except:
                raise AttributeError(
                    "%s object \'%s\' has no attribute \'%s\'" %
                    (type(klass).__name__, klass.__name__, parts[-1]))
Ejemplo n.º 3
0
Archivo: loader.py Proyecto: LJoNe/gpdb
    def loadTestsFromName(self, name, module=None, dryrun=False, expand=True):
        """
        For dynamically generated test methods, loadTestsFromName from unittest.loader will
        raise an error. We handle the case where the test method is not yet generated in this
        implementation of loadTestsFromName.

        @type name: string
        @param name: Name of the test to be loaded. Could be path to a class, module, test method

        @rtype: TINCTestSuite
        @return: The tests loaded for the given name wrapped in a TINCTestSuite
        """
        test_suite = TINCTestSuite()

        # The following block of code is taken from unittest2.loader.loadTestsFromName.
        # It finds the biggest subset from the given name that can be successfully imported.
        parts = name.split('.')
        if module is None:
            parts_copy = parts[:]
            while parts_copy:
                try:
                    m = __import__('.'.join(parts_copy))
                    break
                except ImportError:
                    del parts_copy[-1]
                    if not parts_copy:
                        raise
            parts = parts[1:]

        obj = m

        # We exclude the last part from the name which could potentially be a test method
        # that is not generated yet.
        for part in parts[:-1]:
            parent, obj = obj, getattr(obj, part)

        try:
            parent, obj = obj, getattr(obj, parts[-1])
        except AttributeError, e:
            # This means that the last part is a method which is not yet generated.
            # So we construct an instance of the test class which will dynamically
            # add the test method to its instance.
            #if not issubclass(obj, SQLTestCase):
            #    raise TypeError("don't know how to make test from: %s" % obj)
            try:
                klass = getattr(parent, parts[-2])
                test = klass(parts[-1])
                test_suite.addTest(test)
            except:
                raise AttributeError("%s object \'%s\' has no attribute \'%s\'"%(type(klass).__name__,
                                                                                 klass.__name__,
                                                                                 parts[-1]))
Ejemplo n.º 4
0
    def _construct_scenario_step(self, test_case_list, fail_fast, scenario_steps):
        """
        @type test_case_list: tuple
        @param test_case_list: A tuple of list of test case names to be added to the scenario and a boolean specifying
                               whether or not to run this step serially.

        @type fail_fast: boolean
        @type fail_fast: If set to True, a step with sequential steps will terminate at the first failure
        
        Given a list of test case names, this will construct the actual list of test methods with arguments
        that will be executed concurrently for the scenario step.

        In addition, this will also populate the class level fixtures that should be executed before and after
        the execution the scenario step - namely, the setUpClass and tearDownClass fixtures for all the classes
        added to the scenario step.

        Returns a list of steps that would be constructed for a given test case list. If the test case list happens to contain
        a scenario test case , this will expand the contained scenario test case and add the resulting steps from the contained
        scenario test case
        """
        is_serial = test_case_list[1]
        scenario_step = _ScenarioStep(is_serial=is_serial, fail_fast=fail_fast)
        scenario_steps.append(scenario_step)
        
        # Construct a list of all test methods that will be executed concurrently
        for test_case in test_case_list[0]:

            # Form the test case 3-tuple (name, list of non-keyword args, dict of keyword args)
            test_case = self._construct_test_case_tuple(test_case)

            tincloader = tinctest.TINCTestLoader()
            # Load the test into the scenario
            try:
                test_suite = tincloader.loadTestsFromName(test_case[0])
            except Exception, e:
                raise ScenarioTestCaseException('Exception while loading test into the scenario - %s: %s' %(test_case[0], e))
            
            flat_test_suite = TINCTestSuite()
            self._flatten_test_suite(test_suite, flat_test_suite)
            for test in flat_test_suite:
                if isinstance(test, ScenarioTestCase):
                    # Do not add it to the step if it is a scenario test case
                    # If a contained test case is another ScenarioTestcase, then add the steps of the contained test case
                    # to the current scenario test case
                    test_scenario = self._construct_scenario_for_test(test)
                    for step in test_scenario.steps:
                        scenario_steps.append(step)
                    continue
                
                scenario_step.tests[test.name] = (test, test_case[1], test_case[2])
                # Add setup class / teardown class fixtures that should be executed for this scenario step
                full_class_name = test.__module__ + '.' + test.__class__.__name__
                setUpClass = getattr(test.__class__, 'setUpClass', None)
                tearDownClass = getattr(test.__class__, 'tearDownClass', None)
                if setUpClass and full_class_name not in scenario_step.setup_class_dict:
                    scenario_step.setup_class_dict[full_class_name] = setUpClass
                if tearDownClass and full_class_name not in  scenario_step.teardown_class_dict:
                    scenario_step.teardown_class_dict[full_class_name] = tearDownClass
Ejemplo n.º 5
0
Archivo: loader.py Proyecto: LJoNe/gpdb
    def loadTestsFromTestCase(self, testCaseClass):
        """
        Responsible for loading test cases that belongs to any test class inheriting from TINCTestCase.
        By default, this uses the unittest loader for loading test cases. In addition to the default behavior,
        if the test case class has 'loadTestsFromTestCase' defined and implemented, this will call out to the testCaseClass
        for custom loading of tests for the test case class.

        If the test case class is decorated with 'skipLoading', this will ignore loading for the particular test case class.

        @param testCaseClass: Class object of the test case for which the loading should be performed.
        @type testCaseClass: TINCTestCase class object

        @param consider_skip_loading: boolean that tells whether or not to consider the annotation tinctest.skipLoading
        @type consider_skip_loading: boolean

        @rtype: TINCTestSuite
        @return: Tests loaded for the test case class wrapped in a TINCTestSuite
        """
        # Set all tests loaded to True at the beginning of loading a test class
        testCaseClass._all_tests_loaded = True
        
        # If test case class has the annotation @tinctest.skipLoading, just return
        if self.consider_skip_loading and hasattr(testCaseClass, '__tinc_skip_loading__') and \
               testCaseClass.__tinc_skip_loading__:
            # Check class name and source file to see if it is not inherited
            current_class_name = testCaseClass.__name__
            current_file = sys.modules[testCaseClass.__module__].__file__

            if testCaseClass.__tinc_skip_loading_declared_class__ == current_class_name and \
               testCaseClass.__tinc_skip_loading_declared_file__ == current_file:

                tinctest.logger.info("Skipping test loading for test class %s: %s" %(testCaseClass.__name__,
                                                                                 testCaseClass.__tinc_skip_loading_msg__))
                return TINCTestSuite()
            
        tinctest.logger.debug("Loading tests for test class: %s.%s" %(testCaseClass.__module__, testCaseClass.__name__))
        try:
            test_suite = super(TINCTestLoader, self).loadTestsFromTestCase(testCaseClass)
        except Exception, e:
            # This means that the class did not load properly
            # Add a failure test case to our suite
            test_suite = TINCTestSuite()
            test_suite.addTest(make_failed_test(None, testCaseClass.__module__ + "." + testCaseClass.__name__, e))
            return test_suite
Ejemplo n.º 6
0
 def _flatten_test_suite(self, test_suite, flat_test_suite=TINCTestSuite()):
     """
     Given a test suite that may contain other test suites inside, this creates a flat test suite
     that contains just the tests.
     """
     for test in test_suite._tests:
         if isinstance(test, TINCTestSuite):
             self._flatten_test_suite(test, flat_test_suite)
         else:
             flat_test_suite._tests.append(test)
Ejemplo n.º 7
0
Archivo: main.py Proyecto: 50wu/gpdb
    def _apply_mm_queries(logparser, test_buckets, tincmm_log_config):
        """
        test_buckets contains individual bucket of test tuples based on the above distribution algorithm.

        Construct a test suite for each of the bucket and apply mm queries from tincmm_log_config
        """
        for bucket, idx in zip(test_buckets, range(len(test_buckets))):
            suite = TINCTestSuite()
            for test_tuple in bucket:
                test_case = logparser.dict_of_test_tuples[test_tuple.name].test_case_object
                # LIMITATION: We always set _all_tests_loaded to False for tincmm log parser.
                # It is difficult to find out at this point whether all tests from a test class
                # belongs to the same bucket. Most common use cases will split a test class
                # into multiple buckets and hence we assume that tincmm can operate on the
                # method docstrings
                test_case.__class__._all_tests_loaded = False
                suite.addTest(test_case)

            query_handler = TINCMMQueryHandler(tincmm_log_config.bucket_queries[idx])
            tinc_test_suite_mm = TINCTestSuiteMM(suite)
            tinc_test_suite_mm.apply_queries(query_handler)
Ejemplo n.º 8
0
    def _apply_mm_queries(logparser, test_buckets, tincmm_log_config):
        """
        test_buckets contains individual bucket of test tuples based on the above distribution algorithm.

        Construct a test suite for each of the bucket and apply mm queries from tincmm_log_config
        """
        for bucket, idx in zip(test_buckets, range(len(test_buckets))):
            suite = TINCTestSuite()
            for test_tuple in bucket:
                test_case = logparser.dict_of_test_tuples[
                    test_tuple.name].test_case_object
                # LIMITATION: We always set _all_tests_loaded to False for tincmm log parser.
                # It is difficult to find out at this point whether all tests from a test class
                # belongs to the same bucket. Most common use cases will split a test class
                # into multiple buckets and hence we assume that tincmm can operate on the
                # method docstrings
                test_case.__class__._all_tests_loaded = False
                suite.addTest(test_case)

            query_handler = TINCMMQueryHandler(
                tincmm_log_config.bucket_queries[idx])
            tinc_test_suite_mm = TINCTestSuiteMM(suite)
            tinc_test_suite_mm.apply_queries(query_handler)
Ejemplo n.º 9
0
    def _filter_and_expand(self,
                           test_suite,
                           query_handler=None,
                           dryrun=False,
                           expand=True):
        """
        Filters tests based on tinc queries and expands data provider tests

        Filter:
        If tinc queries are provided (-q option), then filter out any tests case
        that does not satisfy query

        Expand: 
        Inspects each test in the given test suite and looks for tests with data 
        providers and expands the test suite to dynamically add new test methods 
        for the given data provider. Also removes the main data provider test 
        from the suite after expanding which should not be run.
        """
        expanded_filtered = TINCTestSuite(dryrun=dryrun)

        # QAINF-920, all the filtered tests (test not satisfying product_version checks and tinc queries)
        # will not be added to the resulting test suite during normal execution. This is to avoid having the runner execute
        # setUpClass fixtures for test classes that are completely filtered. These tests will not show in test reports
        # as there may be schedules filtering out a lot of tests. Users are expected to do a dryrun to figure out which tests
        # are filtered out because of product_version checks and tinc queries check.
        # TODO: May be show all these tests in normal execution as well in a verbose reporting mode.
        # Note that the skip flag will be handled in TINCTestCase.setUp() since these tests are explicitly skipped by users
        # and we might want to show them out in test reports.

        for test in test_suite._tests:
            # Recurse inside if test suite
            if isinstance(test, unittest.TestSuite):
                expanded_filtered._tests.append(
                    self._filter_and_expand(test,
                                            query_handler,
                                            dryrun=dryrun,
                                            expand=expand))
                continue

            # If it is just a test case object:
            #  - if it has a data_provider, expand the test and remove the
            #    main data_provider test
            #  - apply tinc queries
            if issubclass(test.__class__, TINCTestCase):
                self.total_tests += 1
                if not self._filter_test_case(test, query_handler):
                    if dryrun:
                        expanded_filtered.addTest(test)
                    # no need to anything more since this doesn't satisfy filter checks
                    continue
                self.filtered_tests += 1
                tinctest.logger.debug(
                    "Succeeded tinc filter checks. Adding test: %s" %
                    test.full_name)

                if expand and test.data_provider:
                    tinctest.logger.debug(
                        "dataprovider configured. Expanding test %s" %
                        test.full_name)
                    data_provider_tests = test.add_data_provider_test_methods()
                    for method in data_provider_tests:
                        # the following code makes a copy of the test function
                        # with a side effect that all the instance variables
                        # are also copied as a reference. That is, the original
                        # test function and the test function both will have
                        # references to the same instace variable object. modifying
                        # the variable in one will affect the other
                        # TODO: check if deepcopy can be done
                        new_test = copy.copy(test)
                        new_test._testMethodName = method
                        new_test.full_name = new_test._get_full_name()
                        expanded_filtered.addTest(new_test)
                else:
                    expanded_filtered.addTest(test)
            else:
                expanded_filtered.addTest(test)

        return expanded_filtered
Ejemplo n.º 10
0
    def discover(self,
                 start_dirs,
                 patterns,
                 top_level_dir,
                 query_handler=None,
                 dryrun=False,
                 expand=True):
        """
        Discovers all tests from all start directories provided.
        Tests will be filtered using the query handler.
        @type start_dirs: list
        @param start_dirs: List of directories from where tests should be discovered

        @type patterns: list
        @param patterns: Patterns of test modules from which tests should be discovered.

        @type query_handler: l{TINCDiscoveryQueryHandler}
        @param query_handler: The query handler object that will be used to filter tests based on tinc queries.

        @type dryrun: boolean
        @param dryrun: Boolean to determine whether it is a dry run. True means that no tests will be executed.

        @rtype: TINCTestSuite
        @return: All tests discovered wrapped in a TINCTestSuite
        """
        self.total_tests = 0
        self.filtered_tests = 0
        discovery_start_time = time.time()
        tinctest.logger.status("Started test discovery")

        # Set dryrun for the main test suite that will be returned through
        # discovery

        all_tests = TINCTestSuite(dryrun=dryrun)

        #
        # modules are imported under the top_level_dir. If we are discovering all
        # tests under query, then a test class query.functional.test_dml will be discovered
        # from query directory and the impoted test is functional.test_dml. This causes
        # issues for us if we have dml.functional.test_dml and query.functional.test_dml
        # (and we are discovering "-s dml -s query") because both these classes are
        # discovered as functional.test_dml. So if we are discovering more than one
        # directory we reset the base directory to PWD.
        # See QAINF-935 for more info
        if start_dirs and len(start_dirs) > 1:
            top_level_dir = os.environ.get('PWD', top_level_dir)

        for start_dir in start_dirs:
            discover_dir_start_time = time.time()
            tinctest.logger.info("Started discovering tests from %s" %
                                 start_dir)
            for pattern in patterns:
                pattern_load_start_time = time.time()
                tinctest.logger.info(
                    "Started discovering tests from %s with pattern %s" %
                    (start_dir, pattern))
                self._top_level_dir = None
                # monkey-patch _make_failed_import_test in unittest2.loader to use tinctest.loader's _make_tinc_failed_import_test
                # this is to generate a tinc test case for module import failures that can easily be reported upon in the dry run
                unittest2.loader._make_failed_import_test = _make_tinc_failed_import_test
                test_suite = super(TINCTestLoader,
                                   self).discover(start_dir, pattern,
                                                  top_level_dir)
                pattern_load_elapsed = (time.time() -
                                        pattern_load_start_time) * 1000
                tinctest.logger.info(
                    "Finished loading tests from %s with pattern %s in %4.2f ms"
                    % (start_dir, pattern, pattern_load_elapsed))

                tinctest.logger.info(
                    "Started applying tinc queries for tests from %s with pattern %s"
                    % (start_dir, pattern))
                apply_queries_start_time = time.time()
                for test in test_suite._tests:
                    all_tests.addTest(
                        self._filter_and_expand(test,
                                                query_handler,
                                                dryrun=dryrun,
                                                expand=expand))
                apply_queries_elapsed = (time.time() -
                                         apply_queries_start_time) * 1000
                tinctest.logger.info(
                    "Total tests before querying: %s Total tests after querying: %s"
                    % (self.total_tests, self.filtered_tests))

                tinctest.logger.info(
                    "Finished applying tinc queries for tests from %s with pattern %s in %4.2f ms"
                    % (start_dir, pattern, apply_queries_elapsed))
                pattern_discover_elapsed = (time.time() -
                                            pattern_load_start_time) * 1000
                tinctest.logger.info(
                    "Finished discovering tests from %s with pattern %s in %4.2f ms"
                    % (start_dir, pattern, pattern_discover_elapsed))
            discover_dir_elapsed = (time.time() -
                                    discover_dir_start_time) * 1000
            tinctest.logger.info(
                "Finished discovering tests from %s in %4.2f ms" %
                (start_dir, discover_dir_elapsed))

        discovery_elapsed = (time.time() - discovery_start_time) * 1000
        tinctest.logger.status("Finished test discovery in %4.2f ms. Total tests before querying: %s Total tests after querying: %s" \
                               %(discovery_elapsed,
                                 self.total_tests,
                                 self.filtered_tests))
        return all_tests
Ejemplo n.º 11
0
    def __init__(self, test_suite):
        """
        The constructor stores the following instance variables:
        _tests_mm - List of TINCTestCaseMM objects. One object exists for each TINCTestCase.
        file_name_handlers_dict - Dict of FileHandlers (PythonFileHandler or SQLFileHandler). Key is file path. Value is FileHandler object.
        class_name_metadata_dict - Dict of Metadata dictionary. Key is full class name. Value is metadata dictionary object.
        
        @param test_suite: TINCTestSuite that this MM should work upon
        @type test_suite: L{TINCTestSuite}
        """
        # Flatten the test suite first
        flat_test_suite = TINCTestSuite()
        test_suite.flatten(flat_test_suite)
        self.test_suite = flat_test_suite

        self._tests_mm = []

        # dictionary of file handler objects corresponding to the files where the tests are located
        # This could either be a sql file handler or a (python file handler + sql file handler) for
        # the tests
        self.file_name_handlers_dict = {}

        # dictionary of class metadata corresponding to a completely qualified class name. Multiple tests belonging
        # to the same class will have the same class metadata dict that it should operate upon
        self.class_name_metadata_dict = {}

        # Construct tinc test case mm for every test in the test suite
        for test in self.test_suite:
            # find the file
            test_file = inspect.getsourcefile(inspect.getmodule(test))
            if not test_file in self.file_name_handlers_dict:
                self.file_name_handlers_dict[test_file] = PythonFileHandler(
                    test_file)

            full_class_name = test.full_name.rsplit('.', 1)[0]

            if not full_class_name in self.class_name_metadata_dict:
                self.class_name_metadata_dict[
                    full_class_name] = self.file_name_handlers_dict[
                        test_file].get_metadata_dictionary(
                            method_name=None, class_name=test.class_name)

            class_metadata_dict = self.class_name_metadata_dict[
                full_class_name]

            if self._is_sql_test(test):
                if not test._original_sql_file in self.file_name_handlers_dict:
                    self.file_name_handlers_dict[
                        test._original_sql_file] = SQLFileHandler(
                            test._original_sql_file)
                method_metadata_dict = self.file_name_handlers_dict[
                    test._original_sql_file].get_metadata_dictionary()
            else:
                method_metadata_dict = self.file_name_handlers_dict[
                    test_file].get_metadata_dictionary(
                        class_name=test.class_name,
                        method_name=test.method_name)

            self._tests_mm.append(
                TINCTestCaseMM(test, class_metadata_dict,
                               method_metadata_dict))
Ejemplo n.º 12
0
Archivo: loader.py Proyecto: LJoNe/gpdb
    def _filter_and_expand(self, test_suite, query_handler=None, dryrun=False, expand=True):
        """
        Filters tests based on tinc queries and expands data provider tests

        Filter:
        If tinc queries are provided (-q option), then filter out any tests case
        that does not satisfy query

        Expand: 
        Inspects each test in the given test suite and looks for tests with data 
        providers and expands the test suite to dynamically add new test methods 
        for the given data provider. Also removes the main data provider test 
        from the suite after expanding which should not be run.
        """
        expanded_filtered = TINCTestSuite(dryrun=dryrun)

        # QAINF-920, all the filtered tests (test not satisfying product_version checks and tinc queries)
        # will not be added to the resulting test suite during normal execution. This is to avoid having the runner execute
        # setUpClass fixtures for test classes that are completely filtered. These tests will not show in test reports
        # as there may be schedules filtering out a lot of tests. Users are expected to do a dryrun to figure out which tests
        # are filtered out because of product_version checks and tinc queries check.
        # TODO: May be show all these tests in normal execution as well in a verbose reporting mode. 
        # Note that the skip flag will be handled in TINCTestCase.setUp() since these tests are explicitly skipped by users
        # and we might want to show them out in test reports. 
        
        for test in test_suite._tests:
            # Recurse inside if test suite
            if isinstance(test, unittest.TestSuite):
                expanded_filtered._tests.append(self._filter_and_expand(test, query_handler, dryrun=dryrun, expand=expand))
                continue

            # If it is just a test case object:
            #  - if it has a data_provider, expand the test and remove the 
            #    main data_provider test
            #  - apply tinc queries
            if issubclass(test.__class__, TINCTestCase):
                self.total_tests += 1
                if not self._filter_test_case(test, query_handler):
                    if dryrun:
                        expanded_filtered.addTest(test)
                    # no need to anything more since this doesn't satisfy filter checks
                    continue
                self.filtered_tests += 1
                tinctest.logger.debug("Succeeded tinc filter checks. Adding test: %s" %test.full_name)

                if expand and test.data_provider:
                    tinctest.logger.debug("dataprovider configured. Expanding test %s" %test.full_name)
                    data_provider_tests = test.add_data_provider_test_methods()
                    for method in data_provider_tests:
                        # the following code makes a copy of the test function
                        # with a side effect that all the instance variables
                        # are also copied as a reference. That is, the original
                        # test function and the test function both will have 
                        # references to the same instace variable object. modifying
                        # the variable in one will affect the other
                        # TODO: check if deepcopy can be done
                        new_test = copy.copy(test)
                        new_test._testMethodName = method
                        new_test.full_name = new_test._get_full_name()
                        expanded_filtered.addTest(new_test)
                else:
                    expanded_filtered.addTest(test)
            else:
                expanded_filtered.addTest(test)

            
        return expanded_filtered
Ejemplo n.º 13
0
Archivo: loader.py Proyecto: LJoNe/gpdb
    def discover(self, start_dirs, patterns, top_level_dir, query_handler=None, dryrun=False, expand=True):
        """
        Discovers all tests from all start directories provided.
        Tests will be filtered using the query handler.
        @type start_dirs: list
        @param start_dirs: List of directories from where tests should be discovered

        @type patterns: list
        @param patterns: Patterns of test modules from which tests should be discovered.

        @type query_handler: l{TINCDiscoveryQueryHandler}
        @param query_handler: The query handler object that will be used to filter tests based on tinc queries.

        @type dryrun: boolean
        @param dryrun: Boolean to determine whether it is a dry run. True means that no tests will be executed.

        @rtype: TINCTestSuite
        @return: All tests discovered wrapped in a TINCTestSuite
        """
        self.total_tests = 0
        self.filtered_tests = 0
        discovery_start_time = time.time()
        tinctest.logger.status("Started test discovery")

        # Set dryrun for the main test suite that will be returned through
        # discovery
        
        all_tests = TINCTestSuite(dryrun=dryrun)

        for start_dir in start_dirs:
            discover_dir_start_time = time.time()
            tinctest.logger.info("Started discovering tests from %s" %start_dir)
            for pattern in patterns:
                pattern_load_start_time = time.time()
                tinctest.logger.info("Started discovering tests from %s with pattern %s" %(start_dir, pattern))
                self._top_level_dir = None
                # monkey-patch _make_failed_import_test in unittest2.loader to use tinctest.loader's _make_tinc_failed_import_test
                # this is to generate a tinc test case for module import failures that can easily be reported upon in the dry run
                unittest2.loader._make_failed_import_test = _make_tinc_failed_import_test
                test_suite = super(TINCTestLoader, self).discover(start_dir, pattern, top_level_dir)
                pattern_load_elapsed = (time.time() - pattern_load_start_time) * 1000
                tinctest.logger.info("Finished loading tests from %s with pattern %s in %4.2f ms" %(start_dir, pattern,
                                                                                                    pattern_load_elapsed))

                tinctest.logger.info("Started applying tinc queries for tests from %s with pattern %s" %(start_dir, pattern))
                apply_queries_start_time = time.time()
                for test in test_suite._tests:
                    all_tests.addTest(self._filter_and_expand(test, query_handler, dryrun=dryrun, expand=expand))
                apply_queries_elapsed = (time.time() - apply_queries_start_time) * 1000
                tinctest.logger.info("Total tests before querying: %s Total tests after querying: %s" %(self.total_tests,
                                                                                                        self.filtered_tests))
                
                tinctest.logger.info("Finished applying tinc queries for tests from %s with pattern %s in %4.2f ms" %(start_dir,
                                                                                                                      pattern,
                                                                                                                      apply_queries_elapsed
                                                                                                                      ))
                pattern_discover_elapsed = (time.time() - pattern_load_start_time) * 1000
                tinctest.logger.info("Finished discovering tests from %s with pattern %s in %4.2f ms" %(start_dir, pattern,
                                                                                                         pattern_discover_elapsed))
            discover_dir_elapsed = (time.time() - discover_dir_start_time) * 1000
            tinctest.logger.info("Finished discovering tests from %s in %4.2f ms" %(start_dir, discover_dir_elapsed))

        discovery_elapsed = (time.time() - discovery_start_time) * 1000
        tinctest.logger.status("Finished test discovery in %4.2f ms. Total tests before querying: %s Total tests after querying: %s" \
                               %(discovery_elapsed,
                                 self.total_tests,
                                 self.filtered_tests))
        return all_tests