def provider_by_type(metafunc, provider_types, *fields): """Get the values of the named field keys from ``cfme_data['management_systems']`` Args: provider_types: A list of provider types to include. If None, all providers are considered *fields: Names of keys in an individual provider dict whose values will be returned when used as test function arguments The following test function arguments are special: ``provider_data`` the entire provider data dict from cfme_data. ``provider_key`` the provider's key in ``cfme_data['management_systems']`` ``provider_crud`` the provider's CRUD object, either a :py:class:`cfme.cloud.provider.Provider` or a :py:class:`cfme.infrastructure.provider.Provider` ``provider_mgmt`` the provider's backend manager, from :py:class:`utils.mgmt_system` Returns: An tuple of ``(argnames, argvalues, idlist)`` for use in a pytest_generate_tests hook, or with the :py:func:`parametrize` helper. Usage: # In the function itself def pytest_generate_tests(metafunc): argnames, argvalues, idlist = testgen.provider_by_type( ['openstack', 'ec2'], 'type', 'name', 'credentials', 'provider_data', 'hosts' ) metafunc.parametrize(argnames, argvalues, ids=idlist, scope='module') # Using the parametrize wrapper pytest_generate_tests = testgen.parametrize(testgen.provider_by_type, ['openstack', 'ec2'], 'type', 'name', 'credentials', 'provider_data', 'hosts', scope='module') Note: Using the default 'function' scope, each test will be run individually for each provider before moving on to the next test. To group all tests related to single provider together, parametrize tests in the 'module' scope. """ argnames = list(fields) argvalues = [] idlist = [] special_args = ("provider_key", "provider_data", "provider_crud", "provider_mgmt", "provider_type") # Hook on special attrs if requested for argname in special_args: if argname in metafunc.fixturenames and argname not in argnames: argnames.append(argname) for provider, data in cfme_data["management_systems"].iteritems(): prov_type = data["type"] if provider_types is not None and prov_type not in provider_types: # Skip unwanted types continue # Check provider hasn't been filtered out with --use-provider if provider not in filtered: continue # Use the provider name for idlist, helps with readable parametrized test output idlist.append(provider) # Get values for the requested fields, filling in with None for undefined fields data_values = {field: data.get(field, None) for field in fields} # Go through the values and handle the special 'data' name # report the undefined fields to the log for key, value in data_values.iteritems(): if value is None: logger.warning('Field "%s" not defined for provider "%s", defaulting to None' % (key, provider)) if prov_type in cloud_provider_type_map: crud = get_cloud_provider(provider) elif prov_type in infra_provider_type_map: crud = get_infra_provider(provider) # else: wat? You deserve the NameError you're about to receive mgmt = provider_factory(provider) values = [] special_args_map = dict(zip(special_args, (provider, data, crud, mgmt, prov_type))) for arg in argnames: if arg in special_args_map: values.append(special_args_map[arg]) elif arg in data_values: values.append(data_values[arg]) argvalues.append(values) return argnames, argvalues, idlist
def provider_by_type(metafunc, provider_types, *fields): """Get the values of the named field keys from ``cfme_data['management_systems']`` Args: provider_types: A list of provider types to include. If None, all providers are considered *fields: Names of keys in an individual provider dict whose values will be returned when used as test function arguments The following test function arguments are special: ``provider_data`` the entire provider data dict from cfme_data. ``provider_key`` the provider's key in ``cfme_data['management_systems']`` ``provider_crud`` the provider's CRUD object, either a :py:class:`cfme.cloud.provider.Provider` or a :py:class:`cfme.infrastructure.provider.Provider` ``provider_mgmt`` the provider's backend manager, from :py:class:`utils.mgmt_system` Returns: An tuple of ``(argnames, argvalues, idlist)`` for use in a pytest_generate_tests hook, or with the :py:func:`parametrize` helper. Usage: # In the function itself def pytest_generate_tests(metafunc): argnames, argvalues, idlist = testgen.provider_by_type( ['openstack', 'ec2'], 'type', 'name', 'credentials', 'provider_data', 'hosts' ) metafunc.parametrize(argnames, argvalues, ids=idlist, scope='module') # Using the parametrize wrapper pytest_generate_tests = testgen.parametrize(testgen.provider_by_type, ['openstack', 'ec2'], 'type', 'name', 'credentials', 'provider_data', 'hosts', scope='module') Note: Using the default 'function' scope, each test will be run individually for each provider before moving on to the next test. To group all tests related to single provider together, parametrize tests in the 'module' scope. """ argnames = list(fields) argvalues = [] idlist = [] special_args = ('provider_key', 'provider_data', 'provider_crud', 'provider_mgmt', 'provider_type') # Hook on special attrs if requested for argname in special_args: if argname in metafunc.fixturenames and argname not in argnames: argnames.append(argname) for provider, data in cfme_data['management_systems'].iteritems(): prov_type = data['type'] if provider_types is not None and prov_type not in provider_types: # Skip unwanted types continue # Check provider hasn't been filtered out with --use-provider if provider not in filtered: continue # Use the provider name for idlist, helps with readable parametrized test output idlist.append(provider) # Get values for the requested fields, filling in with None for undefined fields data_values = {field: data.get(field, None) for field in fields} # Go through the values and handle the special 'data' name # report the undefined fields to the log for key, value in data_values.iteritems(): if value is None: logger.warning('Field "%s" not defined for provider "%s", defaulting to None' % (key, provider) ) if prov_type in cloud_provider_type_map: crud = get_cloud_provider(provider) elif prov_type in infra_provider_type_map: crud = get_infra_provider(provider) # else: wat? You deserve the NameError you're about to receive mgmt = provider_factory(provider) values = [] special_args_map = dict(zip(special_args, (provider, data, crud, mgmt, prov_type))) for arg in argnames: if arg in special_args_map: values.append(special_args_map[arg]) elif arg in data_values: values.append(data_values[arg]) argvalues.append(values) return argnames, argvalues, idlist
def provider_by_type(metafunc, provider_types, *fields, **options): """Get the values of the named field keys from ``cfme_data.get('management_systems', {})`` Args: provider_types: A list of provider types to include. If None, all providers are considered *fields: Names of keys in an individual provider dict whose values will be returned when used as test function arguments **options: Explained below The ``**options`` available are defined below: * ``required_fields``: when fields passed are not present, skip them * ``choose_random``: choose a single provider from the list * ``template_location``: Specification where a required tempalte lies in the yaml, If not found in the provider, warning is printed and the test not collected. The spec is a tuple or list where each item is a key to the next field (str or int). The following test function arguments are special: ``provider_data`` the entire provider data dict from cfme_data. ``provider_key`` the provider's key in ``cfme_data.get('management_systems', {})`` ``provider_crud`` the provider's CRUD object, either a :py:class:`cfme.cloud.provider.Provider` or a :py:class:`cfme.infrastructure.provider.Provider` ``provider_mgmt`` the provider's backend manager, from :py:class:`utils.mgmt_system` Returns: An tuple of ``(argnames, argvalues, idlist)`` for use in a pytest_generate_tests hook, or with the :py:func:`parametrize` helper. Usage: # In the function itself def pytest_generate_tests(metafunc): argnames, argvalues, idlist = testgen.provider_by_type( ['openstack', 'ec2'], 'type', 'name', 'credentials', 'provider_data', 'hosts' ) metafunc.parametrize(argnames, argvalues, ids=idlist, scope='module') # Using the parametrize wrapper pytest_generate_tests = testgen.parametrize(testgen.provider_by_type, ['openstack', 'ec2'], 'type', 'name', 'credentials', 'provider_data', 'hosts', scope='module') Note: Using the default 'function' scope, each test will be run individually for each provider before moving on to the next test. To group all tests related to single provider together, parametrize tests in the 'module' scope. Note: testgen for providers now requires the usage of test_flags for collection to work. Please visit http://cfme-tests.readthedocs.org/guides/documenting.html#documenting-tests for more details. """ metafunc.function = pytest.mark.uses_testgen()(metafunc.function) argnames = list(fields) argvalues = [] idlist = [] template_location = options.pop("template_location", None) special_args = ('provider_key', 'provider_data', 'provider_crud', 'provider_mgmt', 'provider_type') # Hook on special attrs if requested for argname in special_args: if argname in metafunc.fixturenames and argname not in argnames: argnames.append(argname) for provider, data in cfme_data.get('management_systems', {}).iteritems(): skip = False prov_type = data['type'] if provider_types is not None and prov_type not in provider_types: # Skip unwanted types continue # Test to see the test has meta data, if it does and that metadata contains # a test_flag kwarg, then check to make sure the provider contains that test_flag # if not, do not collect the provider for this particular test. # Obtain the tests flags meta = getattr(metafunc.function, 'meta', None) test_flags = getattr(meta, 'kwargs', {}) \ .get('from_docs', {}).get('test_flag', '').split(',') if test_flags != ['']: test_flags = [flag.strip() for flag in test_flags] defined_flags = cfme_data.get('test_flags', '').split(',') defined_flags = [flag.strip() for flag in defined_flags] excluded_flags = data.get('excluded_test_flags', '').split(',') excluded_flags = [flag.strip() for flag in excluded_flags] allowed_flags = set(defined_flags) - set(excluded_flags) if set(test_flags) - allowed_flags: logger.info("Skipping Provider {} for test {} in module {} because " "it does not have the right flags, " "{} does not contain {}".format(provider, metafunc.function.func_name, metafunc.function.__module__, list(allowed_flags), list(set(test_flags) - allowed_flags))) continue try: if prov_type == "scvmm" and version.current_version() < "5.3": # Ignore SCVMM on 5.2 continue except Exception: # No SSH connection continue # Check provider hasn't been filtered out with --use-provider if provider not in filtered: continue # Use the provider name for idlist, helps with readable parametrized test output idlist.append(provider) # Get values for the requested fields, filling in with None for undefined fields data_values = {field: data.get(field, None) for field in fields} # Go through the values and handle the special 'data' name # report the undefined fields to the log for key in data_values.keys(): if data_values[key] is None: if 'require_fields' not in options: options['require_fields'] = True if options['require_fields']: skip = True try: idlist.remove(provider) except ValueError: pass logger.warning('Field "%s" not defined for provider "%s", skipping' % (key, provider) ) else: logger.debug('Field "%s" not defined for provider "%s", defaulting to None' % (key, provider) ) # Check the template presence if requested if template_location is not None: o = data try: for field in template_location: o = o[field] except (IndexError, KeyError): logger.info("Cannot apply {} to {} in the template specification, ignoring.".format( repr(field), repr(o))) else: if not isinstance(o, basestring): raise ValueError("{} is not a string! (for template)".format(repr(o))) templates = TEMPLATES.get(provider, None) if templates is not None: if o not in templates: logger.info( "Wanted template {} on {} but it is not there!\n".format(o, provider)) # Skip collection of this one continue if prov_type in cloud_provider_type_map: crud = get_cloud_provider(provider) elif prov_type in infra_provider_type_map: crud = get_infra_provider(provider) # else: wat? You deserve the NameError you're about to receive mgmt = provider_factory(provider) values = [] special_args_map = dict(zip(special_args, (provider, data, crud, mgmt, prov_type))) for arg in argnames: if arg in special_args_map: if arg == "provider_crud": metafunc.function = pytest.mark.provider_related()(metafunc.function) values.append(special_args_map[arg]) elif arg in data_values: values.append(data_values[arg]) # skip when required field is not present and option['require_field'] == True if not skip: argvalues.append(values) # pick a single provider if option['choose_random'] == True if 'choose_random' not in options: options['choose_random'] = False if idlist and options['choose_random']: single_index = idlist.index(random.choice(idlist)) new_idlist = ['random_provider'] new_argvalues = [argvalues[single_index]] logger.debug('Choosing random provider, "%s" selected, ' % (provider)) return argnames, new_argvalues, new_idlist return argnames, argvalues, idlist