Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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