def add_data_provider_test_methods(self): """ If the test has a data provider, this will generate a list of additional tests one for each set of data returned by the data provider configured for this test. For eg: if a data provider configured for a test 'test_method' returns {'key1': 'data1', 'key2': 'data2'}, this method will return a list of tests ['test_method_key1', 'test_method_key2'] with self.test_data set to 'data1' and 'data2' respectively. @rtype: list @return: Returns a list of test cases that has the same logic as the given test case with self.test_data set for each generated test case to an item returned by the data provider configured for this test. """ test_name = '%s.%s.%s' %(self.__class__.__module__, self.__class__.__name__, self._testMethodName) data_provider_tests = [] dict_of_test_data_dicts = {} for each_data_provider in self.data_provider.strip().split(): each_data_provider_func = self._find_data_provider(each_data_provider) each_test_data_dict = each_data_provider_func() if not each_test_data_dict: raise tinctest.TINCException("Data provider %s for test %s should return some data" %(each_data_provider, test_name)) if not type(each_test_data_dict) is dict: raise tinctest.TINCException("Data provider %s for test %s should return a dict" %(each_data_provider, test_name)) dict_of_test_data_dicts[each_data_provider] = each_test_data_dict if len(dict_of_test_data_dicts) == 1: # Just one data provider. Handle it so that none of the existing usage breaks. # test_data will be a simple tuple of data key & data value test_data_dict = dict_of_test_data_dicts.values()[0] for key, value in test_data_dict.items(): new_test_method_name = self._testMethodName + '_' + key test_tuple = (key, value) self._add_new_method(test_tuple, new_test_method_name) data_provider_tests.append(new_test_method_name) else: # Multiple data providers. Need to mix-n-match # test_data will be a list of tuples of (data_provider, data_key, data_value) data_providers, test_data_dicts = zip(*dict_of_test_data_dicts.items()) product_list = [dict(zip(data_providers, test_data_dict)) for test_data_dict in itertools.product(*test_data_dicts)] for each_product in sorted(product_list): new_test_method_name = self._testMethodName test_tuple = [] for data_provider,test_data_key in sorted(each_product.items()): test_data_value = dict_of_test_data_dicts[data_provider][test_data_key] new_test_method_name = new_test_method_name + '_' + test_data_key test_tuple.append((data_provider, test_data_key, test_data_value)) self._add_new_method(test_tuple, new_test_method_name) data_provider_tests.append(new_test_method_name) return data_provider_tests
def _find_data_provider(self, each_data_provider): data_provider_function = None if not data_provider_function: # Check if the definition is found somewhere besides the module file... for each_class in inspect.getmro(self.__class__): if data_provider_function: break functions = inspect.getmembers(inspect.getmodule(each_class), predicate=inspect.isfunction) for (name, function) in functions: if hasattr(function, '__is_data_provider__'): if function.__data_provider_name__ == each_data_provider: data_provider_function = function break if not data_provider_function: test_name = '%s.%s.%s' %(self.__class__.__module__, self.__class__.__name__, self._testMethodName) raise tinctest.TINCException("Invalid data provider specified for test - %s" %test_name) return data_provider_function