"""Integration test configuration."""
import logging
from pathlib import Path
import pytest
import yaml
import simtools.utils.general as gen
_logger = logging.getLogger(__name__)
[docs]
def get_list_of_test_configurations(config_files):
"""
Return list of test configuration dictionaries or test names.
Read all configuration files for testing.
Add "--help" and "--version" calls for all applications.
Parameters
----------
config_files: list
List of integration test configuration files.
Returns
-------
list:
list of test names or of configuration dictionaries.
"""
_logger.debug(f"Configuration files: {config_files}")
configs = _read_configs_from_files(config_files)
# list of all applications
# (needs to be sorted for pytest-xdist, see Known Limitations in their website)
_applications = sorted({item["APPLICATION"] for item in configs if "APPLICATION" in item})
for app in _applications:
configs.extend(
[
{"APPLICATION": app, "TEST_NAME": "auto-help", "CONFIGURATION": {"HELP": True}},
{
"APPLICATION": app,
"TEST_NAME": "auto-version",
"CONFIGURATION": {"VERSION": True},
},
{"APPLICATION": app, "TEST_NAME": "auto-no_config"},
]
)
return (
configs,
[
f"{item.get('APPLICATION', 'no-app-name')}_{item.get('TEST_NAME', 'no-test-name')}"
for item in configs
],
)
def _read_configs_from_files(config_files):
"""Read test configuration from files."""
configs = []
for config_file in config_files:
# read config file
# remove new line characters from config - otherwise issues
# with especially long file names
_dict = gen.remove_substring_recursively_from_dict(
gen.collect_data_from_file_or_dict(file_name=config_file, in_dict=None), substring="\n"
)
configs.append(_dict.get("CTA_SIMPIPE", None))
return configs
def _skip_test_for_model_version(config, model_version_requested):
"""Skip test if model version requested is not supported."""
if config.get("MODEL_VERSION_USE_CURRENT") is None or model_version_requested is None:
return
model_version_config = config["CONFIGURATION"]["MODEL_VERSION"]
if model_version_requested != model_version_config:
pytest.skip(
f"Model version requested {model_version_requested} not supported for this test"
)
def _prepare_test_options(config, output_path, model_version=None):
"""
Prepare test configuration.
This means either to write a temporary config file
or to return a single string for single boolean options (e.g., --version).
Change output path and file to paths provided with output_path.
Parameters
----------
config: dict
Dictionary with the configuration for the application test.
output_path: str
Output path.
model_version: str
Model versions (default: use those given in config files)
Returns
-------
config_file: str
Path to the temporary configuration file.
config_string: str
Command line configuration as single string.
config_file_model_version: str
Configuration file model version
"""
if len(config) == 1 and next(iter(config.values())) is True:
return None, "--" + next(iter(config.keys())).lower(), None
tmp_config_file = output_path / "tmp_config.yml"
config_file_model_version = config.get("MODEL_VERSION")
if model_version is not None and "MODEL_VERSION" in config:
config.update({"MODEL_VERSION": model_version})
if "OUTPUT_PATH" in config:
config.update({"OUTPUT_PATH": str(Path(output_path).joinpath(config["OUTPUT_PATH"]))})
config.update({"USE_PLAIN_OUTPUT_PATH": True})
if "DATA_DIRECTORY" in config:
config.update({"DATA_DIRECTORY": str(Path(output_path).joinpath(config["DATA_DIRECTORY"]))})
_logger.info(f"Writing config file: {tmp_config_file}")
with open(tmp_config_file, "w", encoding="utf-8") as file:
yaml.safe_dump(config, file, sort_keys=False)
return tmp_config_file, None, config_file_model_version
[docs]
def get_application_command(app, config_file=None, config_string=None):
"""
Return the command to run the application with the given config file.
Parameters
----------
app: str
Name of the application.
config_file: str
Configuration file.
config_string: str
Configuration string (e.g., '--version')
Returns
-------
str: command to run the application test.
"""
cmd = app if "simtools-" in app else f"python simtools/applications/{app}.py"
if config_string:
return f"{cmd} {config_string}"
if config_file is not None:
return f"{cmd} --config {config_file}"
return cmd
[docs]
def create_tmp_output_path(tmp_test_directory, config):
"""
Create temporary output path.
Parameters
----------
tmp_test_directory: str
Temporary directory.
config: dict
Configuration dictionary.
Returns
-------
str: path to the temporary output directory.
"""
try:
tmp_output_path = Path(tmp_test_directory).joinpath(
config["APPLICATION"] + "-" + config["TEST_NAME"]
)
except KeyError as exc:
raise KeyError(f"No application defined in configuration {config}.") from exc
tmp_output_path.mkdir(parents=True, exist_ok=True)
_logger.info(f"Temporary output path: {tmp_output_path}")
return tmp_output_path