in azdev/operations/testtool/__init__.py [0:0]
def _discover_tests(profile, target_tests):
""" Builds an index of tests so that the user can simply supply the name they wish to test instead of the
full path.
"""
profile_split = profile.split('-')
profile_namespace = '_'.join([profile_split[-1]] + profile_split[:-1])
heading('Discovering Tests')
path_table = get_path_table()
core_modules = path_table['core'].items()
command_modules = path_table['mod'].items()
extensions = path_table['ext'].items()
inverse_name_table = get_name_index(invert=True)
module_data = {}
logger.info('\nCore Modules: %s', ', '.join([name for name, _ in core_modules]))
for mod_name, mod_path in core_modules:
file_path = mod_path
for comp in mod_name.split('-'):
file_path = os.path.join(file_path, comp)
mod_data = {
'alt_name': 'main' if mod_name == 'azure-cli' else mod_name.replace(COMMAND_MODULE_PREFIX, ''),
'filepath': os.path.join(file_path, 'tests'),
'base_path': '{}.tests'.format(mod_name).replace('-', '.'),
'files': {}
}
tests = _discover_module_tests(mod_name, mod_data)
if tests:
module_data[mod_name] = tests
logger.info('\nCommand Modules: %s', ', '.join([name for name, _ in command_modules]))
for mod_name, mod_path in command_modules:
mod_data = {
# Modules don't technically have azure-cli-foo moniker anymore, but preserving
# for consistency.
'alt_name': '{}{}'.format(COMMAND_MODULE_PREFIX, mod_name),
'filepath': os.path.join(
mod_path, 'tests', profile_namespace),
'base_path': 'azure.cli.command_modules.{}.tests.{}'.format(mod_name, profile_namespace),
'files': {}
}
tests = _discover_module_tests(mod_name, mod_data)
if tests:
module_data[mod_name] = tests
logger.info('\nExtensions: %s', ', '.join([name for name, _ in extensions if name]))
for mod_name, mod_path in extensions:
glob_pattern = os.path.normcase(os.path.join('{}*'.format(EXTENSION_PREFIX)))
try:
file_path = glob.glob(os.path.join(mod_path, glob_pattern))[0]
except IndexError:
logger.debug("No extension found at: %s", os.path.join(mod_path, glob_pattern))
continue
import_name = os.path.basename(file_path)
mod_data = {
'alt_name': inverse_name_table[mod_name],
'filepath': os.path.join(file_path, 'tests', profile_namespace),
'base_path': '{}.tests.{}'.format(import_name, profile_namespace),
'files': {}
}
tests = _discover_module_tests(import_name, mod_data)
if tests:
module_data[mod_name] = tests
test_index = {}
conflicted_keys = []
def add_to_index(key, path):
from azdev.utilities import extract_module_name
key = key or mod_name
if key in test_index:
if key not in conflicted_keys:
conflicted_keys.append(key)
mod1 = extract_module_name(path)
mod2 = extract_module_name(test_index[key])
if mod1 != mod2:
# resolve conflicted keys by prefixing with the module name and a dot (.)
if key in target_tests or mod1 in target_tests or mod2 in target_tests:
logger.warning("'%s' exists in both '%s' and '%s'. Resolve using `%s.%s` or `%s.%s`"
"Duplication exists in: \n\t%s\n\t%s\n",
key, mod1, mod2, mod1, key, mod2, key, path, test_index[key])
test_index['{}.{}'.format(mod1, key)] = path
test_index['{}.{}'.format(mod2, key)] = test_index[key]
else:
if key in target_tests or mod1 in target_tests:
logger.error("'%s' exists twice in the '%s' module. "
"Please rename one or both and re-run --discover. "
"Duplication exists in: \n\t%s\n\t%s\n", key, mod1, test_index[key], path)
else:
test_index[key] = path
# build the index
for mod_name, mod_data in module_data.items():
# don't add empty mods to the index
if not mod_data:
continue
mod_path = mod_data['filepath']
for file_name, file_data in mod_data['files'].items():
file_path = os.path.join(mod_path, file_name) + '.py'
for class_name, test_list in file_data.items():
for test_name in test_list:
test_path = '{}::{}::{}'.format(file_path, class_name, test_name)
add_to_index(test_name, test_path)
class_path = '{}::{}'.format(file_path, class_name)
add_to_index(class_name, class_path)
add_to_index(file_name, file_path)
add_to_index(mod_name, mod_path)
add_to_index(mod_data['alt_name'], mod_path)
# remove the conflicted keys since they would arbitrarily point to a random implementation
for key in conflicted_keys:
del test_index[key]
return test_index