mirror of https://github.com/ceph/ceph-ansible.git
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 <aschoen@redhat.com>pull/1150/head
parent
870a4358f0
commit
c02ffdb0e0
|
@ -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
|
||||
)
|
||||
@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 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)
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue