From c02ffdb0e0865585e03f3451d9e347a30ba6e150 Mon Sep 17 00:00:00 2001 From: Andrew Schoen Date: Sat, 3 Dec 2016 08:07:09 -0600 Subject: [PATCH] tests: change conftest.py to support dynamic markers and test selection This applies correct markers to tests depending on their file path. Tests that live at the root of tests/functional/tests will be given a marker of 'all' and apply to any type of ceph node. Tests that live in tests/functional/tests/mon will get the 'mons' marker and will only run for nodes in the 'mons' group. Tests that live in tests/functional/tests/osd will get the 'osds' marker and will only run for nodes in the 'osds' group. All tests must use the CephNode fixture for this to work and be parameterized by testinfra. Signed-off-by: Andrew Schoen --- tests/conftest.py | 119 ++++++++-------------------------------------- 1 file changed, 21 insertions(+), 98 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 0c054050f..a51f7d940 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,101 +1,24 @@ -import os - import pytest -import imp - - -def pytest_addoption(parser): - default = 'scenario.py' - parser.addoption( - "--scenario", - action="store", - default=default, - help="YAML file defining scenarios to test. Currently defaults to: %s" % default - ) - - -def load_scenario_config(filepath, **kw): - ''' - Creates a configuration dictionary from a file. - - :param filepath: The path to the file. - ''' - - abspath = os.path.abspath(os.path.expanduser(filepath)) - conf_dict = {} - if not os.path.isfile(abspath): - raise RuntimeError('`%s` is not a file.' % abspath) - - # First, make sure the code will actually compile (and has no SyntaxErrors) - with open(abspath, 'rb') as f: - compiled = compile(f.read(), abspath, 'exec') - - # Next, attempt to actually import the file as a module. - # This provides more verbose import-related error reporting than exec() - absname, _ = os.path.splitext(abspath) - basepath, module_name = absname.rsplit(os.sep, 1) - imp.load_module( - module_name, - *imp.find_module(module_name, [basepath]) - ) - - # If we were able to import as a module, actually exec the compiled code - exec(compiled, globals(), conf_dict) - conf_dict['__file__'] = abspath - return conf_dict - - -def pytest_configure_node(node): - node_id = node.slaveinput['slaveid'] - scenario_path = os.path.abspath(node.config.getoption('--scenario')) - scenario = load_scenario_config(scenario_path) - node.slaveinput['node_config'] = scenario['nodes'][node_id] - node.slaveinput['scenario_config'] = scenario - - -@pytest.fixture(scope='session') -def node_config(request): - return request.config.slaveinput['node_config'] - - -@pytest.fixture(scope="session") -def scenario_config(request): - return request.config.slaveinput['scenario_config'] - - -def pytest_report_header(config): - """ - Hook to add extra information about the execution environment and to be - able to debug what did the magical args got expanded to - """ - lines = [] - scenario_path = str(config.rootdir.join(config.getoption('--scenario'))) - if not config.remote_execution: - lines.append('execution environment: local') - else: - lines.append('execution environment: remote') - lines.append('loaded scenario: %s' % scenario_path) - lines.append('expanded args: %s' % config.extended_args) - return lines - - -def pytest_cmdline_preparse(args, config): - # Note: we can only do our magical args expansion if we aren't already in - # a remote node via xdist/execnet so return quickly if we can't do magic. - # TODO: allow setting an environment variable that helps to skip this kind - # of magical argument expansion - if os.getcwd().endswith('pyexecnetcache'): - return - scenario_path = os.path.abspath(config.getoption('--scenario')) - scenarios = load_scenario_config(scenario_path, args=args) - rsync_dir = os.path.dirname(str(config.rootdir.join('functional'))) - test_path = str(config.rootdir.join('functional/tests')) - nodes = [] - config.remote_execution = True - for node in scenarios.get('nodes', []): - nodes.append('--tx') - nodes.append('vagrant_ssh={node_name}//id={node_name}'.format(node_name=node)) - args[:] = args + ['--max-slave-restart', '0', '--dist=each'] + nodes + ['--rsyncdir', rsync_dir, test_path] - config.extended_args = ' '.join(args) +@pytest.fixture() +def CephNode(Ansible, request): + vars = Ansible.get_variables() + node_type = vars["group_names"][0] + if not request.node.get_marker(node_type): + pytest.skip("Not a valid test for node type") + + +def pytest_collection_modifyitems(session, config, items): + for item in items: + test_path = item.location[0] + if "mon" in test_path: + item.add_marker(pytest.mark.mons) + elif "osd" in test_path: + item.add_marker(pytest.mark.osds) + elif "mds" in test_path: + item.add_marker(pytest.mark.mdss) + elif "rgw" in test_path: + item.add_marker(pytest.mark.rgws) + else: + item.add_marker(pytest.mark.all) -- 2.47.3