From f8423ce79fb96bf513ae27d64bce561a767e71db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Kro=C4=8Dil?= Date: Mon, 30 May 2016 16:18:08 +0200 Subject: [PATCH] Fix uncollect when no data pass through to it (pytest 2.7.0 bug, issue #510) Parametrize using testgen to utilize param check everywhere Rename skip funcs to uncollect so their names match their purpose --- cfme/tests/automate/test_vmware_methods.py | 2 +- cfme/tests/cloud/test_stack.py | 2 +- .../configure/test_db_backup_schedule.py | 4 +-- .../configure/test_log_depot_operation.py | 4 +-- .../infrastructure/test_datastore_analysis.py | 2 +- .../infrastructure/test_host_analysis.py | 3 +- cfme/tests/infrastructure/test_infra_quota.py | 2 +- fixtures/parallelizer/parallelizer_tester.py | 3 +- fixtures/rbac.py | 4 +-- markers/uncollect.py | 8 ++++- utils/testgen.py | 34 +++++++++---------- 11 files changed, 37 insertions(+), 31 deletions(-) diff --git a/cfme/tests/automate/test_vmware_methods.py b/cfme/tests/automate/test_vmware_methods.py index dbc39110f2..bb1b3506a8 100644 --- a/cfme/tests/automate/test_vmware_methods.py +++ b/cfme/tests/automate/test_vmware_methods.py @@ -25,7 +25,7 @@ def pytest_generate_tests(metafunc): argnames, argvalues, idlist = testgen.provider_by_type( metafunc, ['virtualcenter'], required_fields=[['provisioning', 'template']]) - metafunc.parametrize(argnames, argvalues, ids=idlist, scope='module') + testgen.parametrize(metafunc, argnames, argvalues, ids=idlist, scope='module') @pytest.yield_fixture(scope="module") diff --git a/cfme/tests/cloud/test_stack.py b/cfme/tests/cloud/test_stack.py index 53c06c9bad..a38392e7e3 100644 --- a/cfme/tests/cloud/test_stack.py +++ b/cfme/tests/cloud/test_stack.py @@ -14,7 +14,7 @@ def pytest_generate_tests(metafunc): argnames, argvalues, idlist = testgen.provider_by_type( metafunc, ['ec2']) - metafunc.parametrize(argnames, argvalues, ids=idlist, scope='module') + testgen.parametrize(metafunc, argnames, argvalues, ids=idlist, scope='module') def set_grid_view(name): diff --git a/cfme/tests/configure/test_db_backup_schedule.py b/cfme/tests/configure/test_db_backup_schedule.py index 0644bca68f..5ec21e1d77 100644 --- a/cfme/tests/configure/test_db_backup_schedule.py +++ b/cfme/tests/configure/test_db_backup_schedule.py @@ -8,7 +8,7 @@ from datetime import datetime from dateutil.relativedelta import relativedelta from urlparse import urlparse -from utils import conf +from utils import conf, testgen from utils.ssh import SSHClient from utils.wait import wait_for from utils.pretty import Pretty @@ -100,7 +100,7 @@ def pytest_generate_tests(metafunc): argvalues.append(db_backup_data) ids.append(db_backup_data.id) - metafunc.parametrize(argnames, argvalues, ids=ids) + testgen.parametrize(metafunc, argnames, argvalues, ids=ids) def get_schedulable_datetime(): diff --git a/cfme/tests/configure/test_log_depot_operation.py b/cfme/tests/configure/test_log_depot_operation.py index 6e0ce84d9c..48b3c84fa7 100644 --- a/cfme/tests/configure/test_log_depot_operation.py +++ b/cfme/tests/configure/test_log_depot_operation.py @@ -9,7 +9,7 @@ import pytest import re from utils.timeutil import parsetime -from utils import conf +from utils import conf, testgen from utils.ftp import FTPClient from utils.path import log_path from cfme.configure import configuration as configure @@ -165,7 +165,7 @@ def get_ftp(depot_type=depot_type): param_tuple = (depot_type, hostname, credentials, get_ftp) if param_tuple not in new_parametrized: new_parametrized.append(param_tuple) - metafunc.parametrize(fixtures, new_parametrized, scope="function") + testgen.parametrize(metafunc, fixtures, new_parametrized, scope="function") @pytest.fixture(scope="function") diff --git a/cfme/tests/infrastructure/test_datastore_analysis.py b/cfme/tests/infrastructure/test_datastore_analysis.py index daccc2b1e8..f1034cbf8d 100644 --- a/cfme/tests/infrastructure/test_datastore_analysis.py +++ b/cfme/tests/infrastructure/test_datastore_analysis.py @@ -48,7 +48,7 @@ def pytest_generate_tests(metafunc): ds['type'])]) test_id = '{}-{}'.format(args['provider'].key, ds['type']) new_idlist.append(test_id) - metafunc.parametrize(argnames, new_argvalues, ids=new_idlist, scope="module") + testgen.parametrize(metafunc, argnames, new_argvalues, ids=new_idlist, scope="module") def get_host_data_by_name(provider_key, host_name): diff --git a/cfme/tests/infrastructure/test_host_analysis.py b/cfme/tests/infrastructure/test_host_analysis.py index b68d1adbdc..e6557eed9a 100644 --- a/cfme/tests/infrastructure/test_host_analysis.py +++ b/cfme/tests/infrastructure/test_host_analysis.py @@ -37,10 +37,9 @@ def pytest_generate_tests(metafunc): argvalues[i] = argvalues[i] + [test_host['type'], test_host['name']] test_id = '{}-{}-{}'.format(args['provider'].key, test_host['type'], test_host['name']) - idlist.append(test_id) new_argvalues.append(argvalues[i]) new_idlist.append(test_id) - metafunc.parametrize(argnames, new_argvalues, ids=new_idlist, scope="module") + testgen.parametrize(metafunc, argnames, new_argvalues, ids=new_idlist, scope="module") def get_host_data_by_name(provider_key, host_name): diff --git a/cfme/tests/infrastructure/test_infra_quota.py b/cfme/tests/infrastructure/test_infra_quota.py index 765ec2173c..c37692ec84 100644 --- a/cfme/tests/infrastructure/test_infra_quota.py +++ b/cfme/tests/infrastructure/test_infra_quota.py @@ -21,7 +21,7 @@ def pytest_generate_tests(metafunc): argnames, argvalues, idlist = testgen.provider_by_type( metafunc, ['virtualcenter']) - metafunc.parametrize(argnames, argvalues, ids=idlist, scope='module') + testgen.parametrize(metafunc, argnames, argvalues, ids=idlist, scope='module') @pytest.fixture(scope="function") diff --git a/fixtures/parallelizer/parallelizer_tester.py b/fixtures/parallelizer/parallelizer_tester.py index a39e818e0f..9b4a0f87c1 100644 --- a/fixtures/parallelizer/parallelizer_tester.py +++ b/fixtures/parallelizer/parallelizer_tester.py @@ -10,6 +10,7 @@ from time import sleep import pytest +from utils import testgen # add 'wait' to this to slow things down, if desired pytestmark = pytest.mark.usefixtures('param') @@ -22,7 +23,7 @@ def pytest_generate_tests(metafunc): ids = [i + 10 for i in xrange(num_copies)] random.shuffle(ids) argvalues = [[v] for v in ids] - metafunc.parametrize(['param'], argvalues, ids=ids, scope='module') + testgen.parametrize(metafunc, ['param'], argvalues, ids=ids, scope='module') @pytest.fixture diff --git a/fixtures/rbac.py b/fixtures/rbac.py index 402caa0fec..8597aa0e1d 100644 --- a/fixtures/rbac.py +++ b/fixtures/rbac.py @@ -97,7 +97,7 @@ def test_rbac(rbac_role): import pytest import traceback from utils.browser import browser, ensure_browser_open -from utils import conf +from utils import conf, testgen enable_rbac = False @@ -225,7 +225,7 @@ def pytest_generate_tests(metafunc): else: roles = ['default'] - metafunc.parametrize('rbac_role', roles) + testgen.parametrize(metafunc, 'rbac_role', roles) def pytest_addoption(parser): diff --git a/markers/uncollect.py b/markers/uncollect.py index fcd4a496e5..52fa9a8224 100644 --- a/markers/uncollect.py +++ b/markers/uncollect.py @@ -77,6 +77,7 @@ def uncollectif(item): except TypeError: logger.debug(log_msg) return not bool(marker.args[0]) + try: values = extract_fixtures_values(item) args = [values[arg] for arg in arg_names] @@ -104,8 +105,13 @@ def pytest_collection_modifyitems(session, config, items): with open(os.path.join(log_path.strpath, 'uncollected.log'), 'w') as f: for item in items: + # Workaround for a known bug in pytest 2.7.0 + # If a test has argnames but no argvalues, it should be ignored (uncollected) + values = extract_fixtures_values(item) + if all(type(v) is object for v in values.itervalues()): + continue # First filter out all items who have the uncollect mark - if item.get_marker('uncollect') or not uncollectif(item): + elif item.get_marker('uncollect') or not uncollectif(item): marker = item.get_marker('uncollectif') if marker: reason = marker.kwargs.get('reason', "No reason given") diff --git a/utils/testgen.py b/utils/testgen.py index 0816a2f116..b5f3823388 100644 --- a/utils/testgen.py +++ b/utils/testgen.py @@ -181,7 +181,7 @@ def fixture_filter(metafunc, argnames, argvalues): return argnames, argvalues -def _skip_restricted_version(data, metafunc, required_fields): +def _uncollect_restricted_version(data, metafunc, required_fields): restricted_version = data.get('restricted_version', None) if restricted_version: logger.info('we found a restricted version') @@ -225,7 +225,7 @@ def _check_required_fields(data, metafunc, required_fields): return False -def _skip_test_flags(data, metafunc, required_fields): +def _uncollect_test_flags(data, metafunc, required_fields): # 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. @@ -246,7 +246,7 @@ def _skip_test_flags(data, metafunc, required_fields): allowed_flags = set(defined_flags) - set(excluded_flags) if set(test_flags) - allowed_flags: - logger.info("Skipping Provider %s for test %s in module %s because " + logger.info("Uncollecting Provider %s for test %s in module %s because " "it does not have the right flags, " "%s does not contain %s", data['name'], metafunc.function.func_name, metafunc.function.__module__, @@ -255,7 +255,7 @@ def _skip_test_flags(data, metafunc, required_fields): return False -def _skip_since_version(data, metafunc, required_fields): +def _uncollect_since_version(data, metafunc, required_fields): try: if "since_version" in data: # Ignore providers that are not supported in this version yet @@ -334,9 +334,6 @@ def pytest_generate_tests(metafunc): argvalues = [] idlist = [] - if 'provider' in metafunc.fixturenames and 'provider' not in argnames: - argnames.append('provider') - for provider in cfme_data.get('management_systems', {}): # Check provider hasn't been filtered out with --use-provider @@ -355,18 +352,21 @@ def pytest_generate_tests(metafunc): if provider_types is not None and prov_obj.type not in provider_types: continue - # Run through all the testgen skip fns - skip = False - skip_fns = [_skip_restricted_version, _check_required_fields, _skip_test_flags, - _skip_since_version] - for fn in skip_fns: + # Run through all the testgen uncollect fns + uncollect = False + uncollect_fns = [_uncollect_restricted_version, _check_required_fields, + _uncollect_test_flags, _uncollect_since_version] + for fn in uncollect_fns: if fn(prov_obj.data, metafunc, required_fields): - skip = True + uncollect = True break - if skip: + if uncollect: continue - # skip when required field is not present and option['require_field'] == True + if 'provider' in metafunc.fixturenames and 'provider' not in argnames: + argnames.append('provider') + + # uncollect when required field is not present and option['require_field'] == True argvalues.append([prov_obj]) # Use the provider name for idlist, helps with readable parametrized test output @@ -514,9 +514,9 @@ def param_check(metafunc, argnames, argvalues): funcname = metafunc.function.__name__ test_name = '.'.join(filter(None, (modname, classname, funcname))) - skip_msg = 'Parametrization for {} yielded no values,'\ + uncollect_msg = 'Parametrization for {} yielded no values,'\ ' marked for uncollection'.format(test_name) - logger.warning(skip_msg) + logger.warning(uncollect_msg) # apply the mark pytest.mark.uncollect()(metafunc.function)