diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 08b77896b80..e0d97fcd9ef 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -18,6 +18,7 @@ env: DOCUMENTATION_CNAME: 'aedt.docs.pyansys.com' ON_CI: True PYTEST_ARGUMENTS: '-vvv --color=yes -ra --durations=25 --maxfail=10 --cov=ansys.aedt.core --cov-report=html --cov-report=xml --junitxml=junit/test-results.xml' + PYAEDT_LOCAL_SETTINGS_PATH: 'tests/pyaedt_settings.yaml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.gitignore b/.gitignore index a950366a84e..caf3b538220 100644 --- a/.gitignore +++ b/.gitignore @@ -372,12 +372,11 @@ dist/ /htmlcov/ /coverage.xml /tests/system/general/coverage.xml -/tests/system/general/local_config.json /tests/system/solvers/coverage.xml -/tests/system/solvers/local_config.json /tests/unit/coverage.xml test-results.xml test-output.xml +*local_config.json # Scratch Jupyter Notebooks scratch_notebooks/ @@ -397,13 +396,10 @@ model.index\+ # local environment settings used by e.g. Visual Studio Code /.env -/doc/source/local_config.json /.venv* # test coverage output /.cov/ -/tests/system/visualization/local_config.json -/tests/system/general/pyaedt_settings.yaml # Custom instructions for GitHub Copilot .github/copilot-instructions.md diff --git a/doc/changelog.d/6727.miscellaneous.md b/doc/changelog.d/6727.miscellaneous.md new file mode 100644 index 00000000000..21431d96fba --- /dev/null +++ b/doc/changelog.d/6727.miscellaneous.md @@ -0,0 +1 @@ +Conftest refactoring and local_config cleaning diff --git a/tests/__init__.py b/tests/__init__.py index 40e2f68aeaf..a482d7aaf37 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -27,8 +27,9 @@ TESTS_PATH = Path(__file__).resolve().parent TESTS_SYSTEM_PATH = TESTS_PATH / "system" TESTS_UNIT_PATH = TESTS_PATH / "unit" +TESTS_EMIT_PATH = TESTS_SYSTEM_PATH / "emit" +TESTS_EXTENSIONS_PATH = TESTS_SYSTEM_PATH / "extensions" +TESTS_FILTER_SOLUTIONS_PATH = TESTS_SYSTEM_PATH / "filter_solutions" TESTS_GENERAL_PATH = TESTS_SYSTEM_PATH / "general" TESTS_SOLVERS_PATH = TESTS_SYSTEM_PATH / "solvers" TESTS_VISUALIZATION_PATH = TESTS_SYSTEM_PATH / "visualization" -TESTS_EXTENSIONS_PATH = TESTS_SYSTEM_PATH / "extensions" -TESTS_FILTER_SOLUTIONS_PATH = TESTS_SYSTEM_PATH / "filter_solutions" diff --git a/tests/conftest.py b/tests/conftest.py index d0ca479bb6a..ea03eba388f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,12 +22,24 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +import json +import os +from pathlib import Path +import random +import shutil +import string import sys +import tempfile from typing import List from unittest.mock import MagicMock import pytest +from ansys.aedt.core.aedt_logger import pyaedt_logger +from ansys.aedt.core.generic.settings import settings +from ansys.aedt.core.internal.filesystem import Scratch + +# Test category prefixes for marker assignment UNIT_TEST_PREFIX = "tests/unit" INTEGRATION_TEST_PREFIX = "tests/integration" SYSTEM_TEST_PREFIX = "tests/system" @@ -39,6 +51,68 @@ EMIT_TEST_PREFIX = "tests/system/emit" +DEFAULT_CONFIG = { + "desktopVersion": "2025.2", + "NonGraphical": True, + "NewThread": True, + "use_grpc": True, + "close_desktop": True, + "remove_lock": False, + "disable_sat_bounding_box": True, + "use_local_example_data": False, + "local_example_folder": None, + "skip_circuits": False, + "skip_modelithics": True, +} + +# Load top-level configuration +local_path = Path(__file__).parent +local_config_file = local_path / "local_config.json" + +config = DEFAULT_CONFIG.copy() +if local_config_file.exists(): + try: + with open(local_config_file) as f: + local_config = json.load(f) + config.update(local_config) + except Exception as e: # pragma: no cover + # Failed to load local_config.json; report error + print(f"Failed to load local_config.json ({local_config_file}): {e}") + +desktop_version = config.get("desktopVersion", DEFAULT_CONFIG.get("desktopVersion")) +NONGRAPHICAL = config.get("NonGraphical", DEFAULT_CONFIG.get("NonGraphical")) +new_thread = config.get("NewThread", DEFAULT_CONFIG.get("NewThread")) +settings.use_grpc_api = config.get("use_grpc", DEFAULT_CONFIG.get("use_grpc")) +close_desktop = config.get("close_desktop", DEFAULT_CONFIG.get("close_desktop")) +remove_lock = config.get("remove_lock", DEFAULT_CONFIG.get("remove_lock")) +settings.disable_bounding_box_sat = config.get( + "disable_sat_bounding_box", DEFAULT_CONFIG.get("disable_sat_bounding_box") +) +settings.use_local_example_data = config.get("use_local_example_data", DEFAULT_CONFIG.get("use_local_example_data")) +if settings.use_local_example_data: + settings.local_example_folder = config.get("local_example_folder", DEFAULT_CONFIG.get("local_example_folder")) + +logger = pyaedt_logger +os.environ["PYAEDT_SCRIPT_VERSION"] = config.get("desktopVersion", DEFAULT_CONFIG.get("desktopVersion")) + + +# Add current path to sys.path for imports +sys.path.append(str(local_path)) + + +def generate_random_string(length): + """Generate a random string of specified length.""" + characters = string.ascii_letters + string.digits + random_string = "".join(random.sample(characters, length)) + return random_string + + +def generate_random_ident(): + """Generate a random identifier for test folders.""" + ident = "-" + generate_random_string(6) + "-" + generate_random_string(6) + "-" + generate_random_string(6) + return ident + + def pytest_collection_modifyitems(config: pytest.Config, items: List[pytest.Item]): """Hook used to apply marker on tests.""" for item in items: @@ -64,8 +138,41 @@ def pytest_collection_modifyitems(config: pytest.Config, items: List[pytest.Item item.add_marker(pytest.mark.emit) +# ================================ +# SHARED FIXTURES +# ================================ + + +@pytest.fixture(scope="session", autouse=True) +def init_scratch(): + """Initialize a global scratch directory for all tests.""" + test_folder_name = "pyaedt_test" + generate_random_ident() + test_folder = Path(tempfile.gettempdir()) / test_folder_name + try: + os.makedirs(test_folder, mode=0o777) + except FileExistsError as e: + print(f"Failed to create {test_folder}. Reason: {e}") + + yield test_folder + + try: + shutil.rmtree(test_folder, ignore_errors=True) + except Exception as e: + print(f"Failed to delete {test_folder}. Reason: {e}") + + +@pytest.fixture(scope="module", autouse=True) +def local_scratch(init_scratch): + """Provide a module-scoped scratch directory.""" + tmp_path = init_scratch + scratch = Scratch(tmp_path) + yield scratch + scratch.remove() + + @pytest.fixture def touchstone_file(tmp_path): + """Create a dummy touchstone file for testing.""" file_path = tmp_path / "dummy.s2p" file_content = """ ! Terminal data exported @@ -80,6 +187,7 @@ def touchstone_file(tmp_path): @pytest.fixture() def patch_graphics_modules(monkeypatch): + """Patch graphics modules to avoid headless env issues.""" modules = [ "matplotlib", "matplotlib.pyplot", @@ -100,9 +208,9 @@ def patch_graphics_modules(monkeypatch): # Specific action to make a mock an attribute of another mock mocks["matplotlib"].pyplot = mocks["matplotlib.pyplot"] - mocks["ansys.tools.visualization_interface"].backends = mocks["ansys.tools.visualization_interface.backends"] - mocks["ansys.tools.visualization_interface.backends"].pyvista = mocks[ - "ansys.tools.visualization_interface.backends.pyvista" - ] + viz_interface = mocks["ansys.tools.visualization_interface"] + viz_backends = mocks["ansys.tools.visualization_interface.backends"] + viz_interface.backends = viz_backends + viz_backends.pyvista = mocks["ansys.tools.visualization_interface.backends.pyvista"] yield mocks diff --git a/tests/pyaedt_settings.yaml b/tests/pyaedt_settings.yaml new file mode 100644 index 00000000000..d508b3655e2 --- /dev/null +++ b/tests/pyaedt_settings.yaml @@ -0,0 +1,18 @@ +# PyAEDT settings configuration for test environment +# This file configures PyAEDT settings for all tests + +log: + enable_local_log_file: false + enable_global_log_file: false + enable_desktop_logs: false + +general: + number_of_grpc_api_retries: 6 + retry_n_times_time_interval: 0.5 + enable_error_handler: false + desktop_launch_timeout: 180 + release_on_exception: false + wait_for_license: true + enable_pandas_output: true +lsf: {} + # LSF settings are kept at defaults for test environment diff --git a/tests/system/conftest.py b/tests/system/conftest.py new file mode 100644 index 00000000000..59bd4a4bde8 --- /dev/null +++ b/tests/system/conftest.py @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +import os +import tempfile + +import pytest + +from ansys.aedt.core import Desktop +from ansys.aedt.core.edb import Edb +from ansys.aedt.core.filtersolutions import DistributedDesign +from ansys.aedt.core.filtersolutions import LumpedDesign +from ansys.aedt.core.generic.file_utils import generate_unique_name +from ansys.aedt.core.hfss import Hfss +from tests import TESTS_EXTENSIONS_PATH +from tests import TESTS_FILTER_SOLUTIONS_PATH +from tests import TESTS_GENERAL_PATH +from tests import TESTS_SOLVERS_PATH +from tests import TESTS_VISUALIZATION_PATH +from tests.conftest import NONGRAPHICAL +from tests.conftest import config + +# Initialize default configuration - shared across all test types +os.environ["ANSYSEM_FEATURE_SS544753_ICEPAK_VIRTUALMESHREGION_PARADIGM_ENABLE"] = "1" + + +@pytest.fixture(scope="module", autouse=True) +def desktop(): + d = Desktop(config["desktopVersion"], NONGRAPHICAL, config["NewThread"]) + d.odesktop.SetTempDirectory(tempfile.gettempdir()) + d.disable_autosave() + + yield d + try: + d.close_desktop() + except Exception: + return False + + +def _get_test_path_from_caller(): + """Determine the appropriate test path based on the calling test's location.""" + import inspect + + # Get the calling frame (skip this function and the fixture) + frame = inspect.currentframe() + try: + # Go up the call stack to find the test file + while frame: + filename = frame.f_code.co_filename + if "test_" in os.path.basename(filename) and "tests" in filename: + if "visualization" in filename: + return TESTS_VISUALIZATION_PATH + elif "solvers" in filename: + return TESTS_SOLVERS_PATH + elif "extensions" in filename: + return TESTS_EXTENSIONS_PATH + elif "filter_solutions" in filename: + return TESTS_FILTER_SOLUTIONS_PATH + else: + return TESTS_GENERAL_PATH + frame = frame.f_back + finally: + del frame + + # Default fallback + return TESTS_GENERAL_PATH + + +@pytest.fixture(scope="module") +def add_app(local_scratch): + def _method( + project_name=None, design_name=None, solution_type=None, application=None, subfolder="", just_open=False + ): + if project_name and not just_open: + # Dynamically determine the correct test path + test_path = _get_test_path_from_caller() + + example_project = os.path.join(test_path, "example_models", subfolder, project_name + ".aedt") + example_folder = os.path.join(test_path, "example_models", subfolder, project_name + ".aedb") + if os.path.exists(example_project): + # Copy unit test project to scratch folder. Return full file path to the project without extension. + test_project = local_scratch.copyfile(example_project) + elif os.path.exists(example_project + "z"): + example_project = example_project + "z" + test_project = local_scratch.copyfile(example_project) + else: + test_project = os.path.join(local_scratch.path, project_name + ".aedt") + if os.path.exists(example_folder): + target_folder = os.path.join(local_scratch.path, project_name + ".aedb") + local_scratch.copyfolder(example_folder, target_folder) + elif project_name and just_open: + test_project = project_name + else: + test_project = None + if not application: + application = Hfss + + args = { + "project": test_project, + "design": design_name, + "version": config["desktopVersion"], + "non_graphical": NONGRAPHICAL, + "remove_lock": True, + } + if solution_type: + args["solution_type"] = solution_type + return application(**args) + + return _method + + +@pytest.fixture(scope="module") +def test_project_file(local_scratch): + def _method(project_name=None, subfolder=None): + if subfolder: + # Dynamically determine the correct test path + test_path = _get_test_path_from_caller() + project_file = os.path.join(test_path, "example_models", subfolder, project_name + ".aedt") + else: + project_file = os.path.join(local_scratch.path, project_name + ".aedt") + if os.path.exists(project_file): + return project_file + else: + return None + + return _method + + +@pytest.fixture(scope="module") +def add_edb(local_scratch): + def _method(project_name=None, subfolder=""): + if project_name: + # Dynamically determine the correct test path + test_path = _get_test_path_from_caller() + example_folder = os.path.join(test_path, "example_models", subfolder, project_name + ".aedb") + if os.path.exists(example_folder): + target_folder = os.path.join(local_scratch.path, project_name + ".aedb") + local_scratch.copyfolder(example_folder, target_folder) + else: + target_folder = os.path.join(local_scratch.path, project_name + ".aedb") + else: + target_folder = os.path.join(local_scratch.path, generate_unique_name("TestEdb") + ".aedb") + return Edb( + target_folder, + edbversion=config["desktopVersion"], + ) + + return _method + + +@pytest.fixture(scope="function") +def lumped_design(): + """Fixture for creating a LumpedDesign object.""" + return LumpedDesign(config["desktopVersion"]) + + +@pytest.fixture(scope="function") +def distributed_design(): + """Fixture for creating a DistributedDesign object.""" + return DistributedDesign(config["desktopVersion"]) diff --git a/tests/system/emit/conftest.py b/tests/system/emit/conftest.py deleted file mode 100644 index efb619e1756..00000000000 --- a/tests/system/emit/conftest.py +++ /dev/null @@ -1,197 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -""" -Unit Test Configuration Module -------------------------------- - -Description -=========== - -This module contains the configuration and fixture for the pytest-based unit tests for PyAEDT. - -The default configuration can be changed by placing a file called local_config.json in the same -directory as this module. An example of the contents of local_config.json -{ - "desktopVersion": "2022.2", - "NonGraphical": false, - "NewThread": false, - "skip_desktop_test": false -} - -""" - -import gc -import json -import os -from pathlib import Path -import random -import shutil -import string -import sys -import tempfile -import time - -import pytest - -from ansys.aedt.core import Emit -from ansys.aedt.core.aedt_logger import pyaedt_logger -from ansys.aedt.core.desktop import Desktop -from ansys.aedt.core.generic.settings import settings -from ansys.aedt.core.internal.desktop_sessions import _desktop_sessions -from ansys.aedt.core.internal.filesystem import Scratch - -local_path = Path(__file__).parent -sys.path.append(str(local_path)) - -# Initialize default desktop configuration -default_version = "2025.2" - -config = { - "desktopVersion": default_version, - "NonGraphical": True, - "NewThread": True, - "use_grpc": True, - "close_desktop": True, - "remove_lock": False, -} - -# Check for the local config file, override defaults if found -local_config_file = Path(local_path) / "local_config.json" -if local_config_file.exists(): - try: - with open(local_config_file) as f: - local_config = json.load(f) - except Exception: # pragma: no cover - local_config = {} - config.update(local_config) - -NONGRAPHICAL = config["NonGraphical"] -desktop_version = config["desktopVersion"] -new_thread = config["NewThread"] -settings.use_grpc_api = config["use_grpc"] -close_desktop = config["close_desktop"] -remove_lock = config["remove_lock"] - -logger = pyaedt_logger - - -def generate_random_string(length): - characters = string.ascii_letters + string.digits - random_string = "".join(random.sample(characters, length)) - return random_string - - -def generate_random_ident(): - ident = "-" + generate_random_string(6) + "-" + generate_random_string(6) + "-" + generate_random_string(6) - return ident - - -@pytest.fixture(scope="session", autouse=True) -def init_scratch(): - test_folder_name = "unit_test" + generate_random_ident() - test_folder = Path(tempfile.gettempdir()) / test_folder_name - try: - os.makedirs(test_folder, mode=0o777) - except FileExistsError as e: - print(f"Failed to create {test_folder}. Reason: {e}") - - yield test_folder - - try: - shutil.rmtree(test_folder, ignore_errors=True) - except Exception as e: - print(f"Failed to delete {test_folder}. Reason: {e}") - - -@pytest.fixture(scope="module", autouse=True) -def local_scratch(init_scratch): - tmp_path = init_scratch - scratch = Scratch(tmp_path) - yield scratch - scratch.remove() - - -def _delete_objects(): - settings.remote_api = False - pyaedt_logger.remove_all_project_file_logger() - try: - del sys.modules["glob"] - except Exception: - logger.debug("Failed to delete glob module") - gc.collect() - - -@pytest.fixture(scope="module", autouse=True) -def desktop(local_scratch): - _delete_objects() - keys = list(_desktop_sessions.keys()) - for key in keys: - del _desktop_sessions[key] - d = Desktop(desktop_version, NONGRAPHICAL, new_thread) - d.odesktop.SetTempDirectory(str(local_scratch.path)) - d.disable_autosave() - if desktop_version > "2022.2": - d.odesktop.SetDesktopConfiguration("All") - d.odesktop.SetSchematicEnvironment(0) - yield d - pid = d.aedt_process_id - d.close_desktop() - time.sleep(1) - try: - os.kill(pid, 9) - except OSError: - pass - - -@pytest.fixture(scope="module") -def add_app(local_scratch): - def _method( - project_name=None, design_name=None, solution_type=None, application=None, subfolder="", just_open=False - ): - if project_name and not just_open: - example_project = Path(local_path) / "example_models" / subfolder / (project_name + ".aedt") - if example_project.exists(): - test_project = local_scratch.copyfile(str(example_project)) - elif example_project.with_suffix(".aedtz").exists(): - example_project = example_project.with_suffix(".aedtz") - test_project = local_scratch.copyfile(str(example_project)) - else: - test_project = Path(local_scratch.path) / (project_name + ".aedt") - elif project_name and just_open: - test_project = project_name - else: - test_project = None - if not application: - application = Emit - return application( - project=test_project, - design=design_name, - solution_type=solution_type, - version=desktop_version, - remove_lock=remove_lock, - non_graphical=NONGRAPHICAL, - ) - - return _method diff --git a/tests/system/emit/test_emit.py b/tests/system/emit/test_emit.py index 69e09d40a76..f789bfb6af0 100644 --- a/tests/system/emit/test_emit.py +++ b/tests/system/emit/test_emit.py @@ -38,7 +38,8 @@ import ansys.aedt.core from ansys.aedt.core.generic import constants as consts from ansys.aedt.core.generic.general_methods import is_linux -from tests.system.solvers.conftest import config +from tests import TESTS_EMIT_PATH +from tests.conftest import config # Prior to 2025R1, the Emit API supported Python 3.8,3.9,3.10,3.11 # Starting with 2025R1, the Emit API supports Python 3.10,3.11,3.12 @@ -60,17 +61,12 @@ from ansys.aedt.core.modeler.circuits.primitives_emit import EmitComponent from ansys.aedt.core.modeler.circuits.primitives_emit import EmitComponents -TEST_REVIEW_FLAG = True -TEST_SUBFOLDER = "TEMIT" +TEST_SUBFOLDER = TESTS_EMIT_PATH / "example_models/TEMIT" @pytest.fixture() def interference(add_app): - app = add_app( - project_name="interference", - application=ansys.aedt.core.Emit, - subfolder=TEST_SUBFOLDER, - ) + app = add_app(project_name="interference", application=ansys.aedt.core.Emit, subfolder=TEST_SUBFOLDER) yield app app.close_project(app.project_name, save=False) diff --git a/tests/system/extensions/conftest.py b/tests/system/extensions/conftest.py deleted file mode 100644 index 168e5e68446..00000000000 --- a/tests/system/extensions/conftest.py +++ /dev/null @@ -1,238 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -""" -Unit Test Configuration Module -------------------------------- - -Description -=========== - -This module contains the configuration and fixture for the pytest-based unit tests for PyAEDT. - -The default configuration can be changed by placing a file called local_config.json in the same -directory as this module. An example of the contents of local_config.json -{ - "desktopVersion": "2022.2", - "NonGraphical": false, - "NewThread": false, - "skip_desktop_test": false -} - -""" - -import json -import os -import random -import shutil -import string -import sys -import tempfile - -import pytest - -from ansys.aedt.core import Desktop -from ansys.aedt.core import Edb -from ansys.aedt.core import Hfss -from ansys.aedt.core.aedt_logger import pyaedt_logger -from ansys.aedt.core.generic.file_utils import generate_unique_name -from ansys.aedt.core.generic.settings import settings -from ansys.aedt.core.internal.filesystem import Scratch - -settings.enable_local_log_file = False -settings.enable_global_log_file = False -settings.number_of_grpc_api_retries = 6 -settings.retry_n_times_time_interval = 0.5 -settings.enable_error_handler = False -settings.enable_desktop_logs = False -settings.desktop_launch_timeout = 180 -settings.release_on_exception = False -settings.wait_for_license = True -settings.enable_pandas_output = True - -local_path = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(local_path) - -# Initialize default desktop configuration -default_version = "2025.2" - -os.environ["ANSYSEM_FEATURE_SS544753_ICEPAK_VIRTUALMESHREGION_PARADIGM_ENABLE"] = "1" - -config = { - "desktopVersion": default_version, - "NonGraphical": True, - "NewThread": True, - "skip_desktop_test": False, - "build_machine": True, - "skip_space_claim": False, - "skip_circuits": False, - "skip_edb": False, - "skip_debug": False, - "skip_modelithics": True, - "local": False, - "use_grpc": True, - "disable_sat_bounding_box": True, - "close_desktop": True, - "remove_lock": False, - "local_example_folder": None, - "use_local_example_data": False, -} - -# Check for the local config file, override defaults if found -local_config_file = os.path.join(local_path, "local_config.json") -if os.path.exists(local_config_file): - try: - with open(local_config_file) as f: - local_config = json.load(f) - except Exception: # pragma: no cover - local_config = {} - config.update(local_config) - -NONGRAPHICAL = config["NonGraphical"] -settings.disable_bounding_box_sat = config["disable_sat_bounding_box"] -desktop_version = config["desktopVersion"] -new_thread = config["NewThread"] -settings.use_grpc_api = config["use_grpc"] - -logger = pyaedt_logger - -os.environ["PYAEDT_SCRIPT_VERSION"] = config["desktopVersion"] - - -def generate_random_string(length): - characters = string.ascii_letters + string.digits - random_string = "".join(random.sample(characters, length)) - return random_string - - -def generate_random_ident(): - ident = "-" + generate_random_string(6) + "-" + generate_random_string(6) + "-" + generate_random_string(6) - return ident - - -@pytest.fixture(scope="session", autouse=True) -def init_scratch(): - test_folder_name = "unit_test" + generate_random_ident() - test_folder = os.path.join(tempfile.gettempdir(), test_folder_name) - try: - os.makedirs(test_folder, mode=0o777) - except FileExistsError as e: - print(f"Failed to create {test_folder}. Reason: {e}") - - yield test_folder - - try: - shutil.rmtree(test_folder, ignore_errors=True) - except Exception as e: - print(f"Failed to delete {test_folder}. Reason: {e}") - - -@pytest.fixture(scope="module", autouse=True) -def local_scratch(init_scratch): - tmp_path = init_scratch - scratch = Scratch(tmp_path) - yield scratch - scratch.remove() - - -@pytest.fixture(scope="module", autouse=True) -def desktop(): - d = Desktop(desktop_version, NONGRAPHICAL, new_thread) - d.odesktop.SetTempDirectory(tempfile.gettempdir()) - d.disable_autosave() - - yield d - try: - d.close_desktop() - except Exception: - return False - - -@pytest.fixture(scope="module") -def add_app(local_scratch): - def _method( - project_name=None, design_name=None, solution_type=None, application=None, subfolder="", just_open=False - ): - if project_name and not just_open: - example_project = os.path.join(local_path, "example_models", subfolder, project_name + ".aedt") - example_folder = os.path.join(local_path, "example_models", subfolder, project_name + ".aedb") - if os.path.exists(example_project): - test_project = local_scratch.copyfile(example_project) - elif os.path.exists(example_project + "z"): - example_project = example_project + "z" - test_project = local_scratch.copyfile(example_project) - else: - test_project = os.path.join(local_scratch.path, project_name + ".aedt") - if os.path.exists(example_folder): - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") - local_scratch.copyfolder(example_folder, target_folder) - elif project_name and just_open: - test_project = project_name - else: - test_project = None - if not application: - application = Hfss - return application( - project=test_project, - design=design_name, - solution_type=solution_type, - version=desktop_version, - ) - - return _method - - -@pytest.fixture(scope="module") -def test_project_file(local_scratch): - def _method(project_name=None, subfolder=None): - if subfolder: - project_file = os.path.join(local_path, "example_models", subfolder, project_name + ".aedt") - else: - project_file = os.path.join(local_scratch.path, project_name + ".aedt") - if os.path.exists(project_file): - return project_file - else: - return None - - return _method - - -@pytest.fixture(scope="module") -def add_edb(local_scratch): - def _method(project_name=None, subfolder=""): - if project_name: - example_folder = os.path.join(local_path, "example_models", subfolder, project_name + ".aedb") - if os.path.exists(example_folder): - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") - local_scratch.copyfolder(example_folder, target_folder) - else: - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") - else: - target_folder = os.path.join(local_scratch.path, generate_unique_name("TestEdb") + ".aedb") - return Edb( - target_folder, - edbversion=desktop_version, - ) - - return _method diff --git a/tests/system/extensions/test_cutout.py b/tests/system/extensions/test_cutout.py index bc550312fcb..75681b6ebd9 100644 --- a/tests/system/extensions/test_cutout.py +++ b/tests/system/extensions/test_cutout.py @@ -32,7 +32,7 @@ from ansys.aedt.core.extensions.hfss3dlayout.cutout import CutoutData from ansys.aedt.core.extensions.hfss3dlayout.cutout import main from ansys.aedt.core.hfss3dlayout import Hfss3dLayout -from tests.system.extensions.conftest import config +from tests.conftest import config AEDB_FILE_NAME = "ANSYS-HSD_V1" TEST_SUBFOLDER = "T45" diff --git a/tests/system/extensions/test_export_layout.py b/tests/system/extensions/test_export_layout.py index 0b2aaac87e6..32b7af1fef3 100644 --- a/tests/system/extensions/test_export_layout.py +++ b/tests/system/extensions/test_export_layout.py @@ -31,7 +31,7 @@ from ansys.aedt.core.extensions.hfss3dlayout.export_layout import ExportLayoutExtensionData from ansys.aedt.core.extensions.hfss3dlayout.export_layout import main from ansys.aedt.core.hfss3dlayout import Hfss3dLayout -from tests.system.extensions.conftest import config +from tests.conftest import config AEDB_FILE_NAME = "ANSYS-HSD_V1" TEST_SUBFOLDER = "T45" diff --git a/tests/system/extensions/test_fields_distribution.py b/tests/system/extensions/test_fields_distribution.py index d43124b522d..37824a6461a 100644 --- a/tests/system/extensions/test_fields_distribution.py +++ b/tests/system/extensions/test_fields_distribution.py @@ -28,7 +28,7 @@ import pytest import ansys.aedt.core -from tests.system.extensions.conftest import local_path as extensions_local_path +from tests import TESTS_EXTENSIONS_PATH # Test project constants fields_distribution_project = "transformer_loss_distribution" @@ -75,7 +75,7 @@ def test_fields_distribution_with_points_file(add_app, local_scratch): from ansys.aedt.core.extensions.maxwell3d.fields_distribution import main file_path = Path(local_scratch.path) / "loss_distribution_points.csv" - points_file = Path(extensions_local_path) / "example_models" / test_subfolder / "hv_terminal.pts" + points_file = Path(TESTS_EXTENSIONS_PATH) / "example_models" / test_subfolder / "hv_terminal.pts" aedtapp = add_app( application=ansys.aedt.core.Maxwell2d, @@ -390,7 +390,7 @@ def test_fields_distribution(add_app, local_scratch): assert file_path.is_file() # Test with points file - points_file = Path(extensions_local_path) / "example_models" / test_subfolder / "hv_terminal.pts" + points_file = Path(TESTS_EXTENSIONS_PATH) / "example_models" / test_subfolder / "hv_terminal.pts" data = FieldsDistributionExtensionData( points_file=str(points_file), export_file=str(file_path), @@ -486,7 +486,7 @@ def test_fields_distribution_comprehensive_scenarios(add_app, local_scratch): assert file_path.is_file() # Test with points file - points_file = Path(extensions_local_path) / "example_models" / test_subfolder / "hv_terminal.pts" + points_file = Path(TESTS_EXTENSIONS_PATH) / "example_models" / test_subfolder / "hv_terminal.pts" data = FieldsDistributionExtensionData( points_file=str(points_file), export_file=str(file_path), diff --git a/tests/system/extensions/test_parametrize_edb.py b/tests/system/extensions/test_parametrize_edb.py index c8a9779b0ec..4f4de0b9677 100644 --- a/tests/system/extensions/test_parametrize_edb.py +++ b/tests/system/extensions/test_parametrize_edb.py @@ -24,7 +24,7 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -import os +from pathlib import Path import pytest @@ -32,7 +32,7 @@ from ansys.aedt.core.extensions.hfss3dlayout.parametrize_edb import main from ansys.aedt.core.generic.settings import is_linux from ansys.aedt.core.internal.errors import AEDTRuntimeError -from tests.system.extensions.conftest import local_path as extensions_local_path +from tests import TESTS_EXTENSIONS_PATH pytest.importorskip("pyedb", "0.21.0") @@ -40,14 +40,14 @@ @pytest.mark.skipif(is_linux, reason="Long test for Linux VM.") def test_parametrize_layout(local_scratch): """Test parametrizing EDB layout with comprehensive settings.""" - file_path = os.path.join(local_scratch.path, "ANSYS-HSD_V1_param.aedb") + file_path = Path(local_scratch.path) / "ANSYS-HSD_V1_param.aedb" local_scratch.copyfolder( - os.path.join(extensions_local_path, "example_models", "T45", "ANSYS-HSD_V1.aedb"), file_path + str(Path(TESTS_EXTENSIONS_PATH) / "example_models" / "T45" / "ANSYS-HSD_V1.aedb"), str(file_path) ) data = ParametrizeEdbExtensionData( - aedb_path=file_path, + aedb_path=str(file_path), parametrize_layers=True, parametrize_materials=True, parametrize_padstacks=True, @@ -92,15 +92,15 @@ def test_parametrize_edb_exceptions(): @pytest.mark.skipif(is_linux, reason="Long test for Linux VM.") def test_parametrize_edb_custom_settings(local_scratch): """Test Parametrize EDB extension with custom settings.""" - file_path = os.path.join(local_scratch.path, "ANSYS-HSD_V1_custom.aedb") + file_path = Path(local_scratch.path) / "ANSYS-HSD_V1_custom.aedb" local_scratch.copyfolder( - os.path.join(extensions_local_path, "example_models", "T45", "ANSYS-HSD_V1.aedb"), file_path + str(Path(TESTS_EXTENSIONS_PATH) / "example_models" / "T45" / "ANSYS-HSD_V1.aedb"), str(file_path) ) # Test with custom parametrization settings data = ParametrizeEdbExtensionData( - aedb_path=file_path, + aedb_path=str(file_path), parametrize_layers=False, parametrize_materials=True, parametrize_padstacks=False, @@ -119,15 +119,15 @@ def test_parametrize_edb_custom_settings(local_scratch): @pytest.mark.skipif(is_linux, reason="Long test for Linux VM.") def test_parametrize_edb_zero_expansions(local_scratch): """Test Parametrize EDB extension with zero expansions.""" - file_path = os.path.join(local_scratch.path, "ANSYS-HSD_V1_zero.aedb") + file_path = Path(local_scratch.path) / "ANSYS-HSD_V1_zero.aedb" local_scratch.copyfolder( - os.path.join(extensions_local_path, "example_models", "T45", "ANSYS-HSD_V1.aedb"), file_path + str(Path(TESTS_EXTENSIONS_PATH) / "example_models" / "T45" / "ANSYS-HSD_V1.aedb"), str(file_path) ) # Test with zero expansions (should work fine) data = ParametrizeEdbExtensionData( - aedb_path=file_path, + aedb_path=str(file_path), expansion_polygon_mm=0.0, expansion_void_mm=0.0, project_name="zero_expansion_project", diff --git a/tests/system/extensions/test_post_layout_design.py b/tests/system/extensions/test_post_layout_design.py index 0963f731c2b..765ebee3872 100644 --- a/tests/system/extensions/test_post_layout_design.py +++ b/tests/system/extensions/test_post_layout_design.py @@ -22,7 +22,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -import os +from pathlib import Path import pytest @@ -30,10 +30,7 @@ from ansys.aedt.core.extensions.hfss3dlayout import post_layout_design from ansys.aedt.core.extensions.hfss3dlayout.post_layout_design import PostLayoutDesignExtensionData from ansys.aedt.core.internal.errors import AEDTRuntimeError -from tests.system.extensions.conftest import local_path as extensions_local_path - -# Get local path for test files -local_path = os.path.dirname(os.path.realpath(__file__)) +from tests import TESTS_EXTENSIONS_PATH def test_post_layout_design_data_class(add_app): @@ -77,15 +74,10 @@ def test_post_layout_design_main_function_exceptions(add_app): def test_layout_design_toolkit_antipad_1(add_app, local_scratch): """Test antipad creation with racetrack enabled.""" - file_path = os.path.join(local_scratch.path, "ANSYS-HSD_V1_antipad_1.aedb") + file_path = Path(local_scratch.path) / "ANSYS-HSD_V1_antipad_1.aedb" local_scratch.copyfolder( - os.path.join( - extensions_local_path, - "example_models", - "post_layout_design", - "ANSYS_SVP_V1_1_SFP.aedb", - ), + Path(TESTS_EXTENSIONS_PATH) / "example_models" / "post_layout_design" / "ANSYS_SVP_V1_1_SFP.aedb", file_path, ) @@ -113,15 +105,10 @@ def test_layout_design_toolkit_antipad_1(add_app, local_scratch): def test_layout_design_toolkit_antipad_2(add_app, local_scratch): """Test antipad creation with racetrack disabled.""" - file_path = os.path.join(local_scratch.path, "ANSYS-HSD_V1_antipad_2.aedb") + file_path = Path(local_scratch.path) / "ANSYS-HSD_V1_antipad_2.aedb" local_scratch.copyfolder( - os.path.join( - extensions_local_path, - "example_models", - "post_layout_design", - "ANSYS_SVP_V1_1_SFP.aedb", - ), + Path(TESTS_EXTENSIONS_PATH) / "example_models" / "post_layout_design" / "ANSYS_SVP_V1_1_SFP.aedb", file_path, ) @@ -149,15 +136,10 @@ def test_layout_design_toolkit_antipad_2(add_app, local_scratch): def test_layout_design_toolkit_unknown_action(add_app, local_scratch): """Test main function with unknown action.""" - file_path = os.path.join(local_scratch.path, "ANSYS-HSD_V1_unknown_action.aedb") + file_path = Path(local_scratch.path) / "ANSYS-HSD_V1_unknown_action.aedb" local_scratch.copyfolder( - os.path.join( - extensions_local_path, - "example_models", - "post_layout_design", - "ANSYS_SVP_V1_1_SFP.aedb", - ), + Path(TESTS_EXTENSIONS_PATH) / "example_models" / "post_layout_design" / "ANSYS_SVP_V1_1_SFP.aedb", file_path, ) @@ -185,15 +167,10 @@ def test_layout_design_toolkit_unknown_action(add_app, local_scratch): @pytest.mark.flaky_linux def test_layout_design_toolkit_microvia(add_app, local_scratch): """Test microvia creation with conical shape.""" - file_path = os.path.join(local_scratch.path, "ANSYS-HSD_V1_microvia.aedb") + file_path = Path(local_scratch.path) / "ANSYS-HSD_V1_microvia.aedb" local_scratch.copyfolder( - os.path.join( - extensions_local_path, - "example_models", - "post_layout_design", - "ANSYS_SVP_V1_1_SFP.aedb", - ), + Path(TESTS_EXTENSIONS_PATH) / "example_models" / "post_layout_design" / "ANSYS_SVP_V1_1_SFP.aedb", file_path, ) diff --git a/tests/system/extensions/test_push_excitation_from_file_3dl.py b/tests/system/extensions/test_push_excitation_from_file_3dl.py index cb31e153122..a2c2fc0a95d 100644 --- a/tests/system/extensions/test_push_excitation_from_file_3dl.py +++ b/tests/system/extensions/test_push_excitation_from_file_3dl.py @@ -24,6 +24,7 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os +from pathlib import Path import shutil import tempfile @@ -35,26 +36,18 @@ from ansys.aedt.core.extensions.hfss3dlayout.push_excitation_from_file_3dl import PushExcitation3DLayoutExtensionData from ansys.aedt.core.extensions.hfss3dlayout.push_excitation_from_file_3dl import main from ansys.aedt.core.internal.errors import AEDTRuntimeError - -# Get local path for test files -local_path = os.path.dirname(os.path.realpath(__file__)) +from tests import TESTS_EXTENSIONS_PATH def test_push_excitation_3dl_generate_button(local_scratch, desktop): """Test the Generate button in the Push Excitation 3D Layout extension.""" - project_path = shutil.copy( - os.path.join( - local_path, - "..", - "general", - "example_models", - "T41", - "test_post_3d_layout_solved_23R2.aedtz", - ), - os.path.join( - local_scratch.path, - "test_post_3d_layout_solved_23R2.aedtz", - ), + project_path = Path( + shutil.copy( + Path( + TESTS_EXTENSIONS_PATH, "..", "general", "example_models", "T41", "test_post_3d_layout_solved_23R2.aedtz" + ), + Path(local_scratch.path, "test_post_3d_layout_solved_23R2.aedtz"), + ) ) h3d = Hfss3dLayout( @@ -75,7 +68,7 @@ def test_push_excitation_3dl_generate_button(local_scratch, desktop): else: voltage = 0.0 tmp_file.write(f"{time},{voltage}\n") - tmp_file_path = tmp_file.name + tmp_file_path = Path(tmp_file.name) try: # Get available excitation names @@ -85,14 +78,14 @@ def test_push_excitation_3dl_generate_button(local_scratch, desktop): # Use the first available excitation excitation_name = excitation_names[0] - data = PushExcitation3DLayoutExtensionData(choice=excitation_name, file_path=tmp_file_path) + data = PushExcitation3DLayoutExtensionData(choice=excitation_name, file_path=str(tmp_file_path)) extension = PushExcitation3DLayoutExtension(withdraw=True) # Set up the UI controls with test data before invoking button extension.port_combo.set(excitation_name) extension.file_entry.delete("1.0", "end") - extension.file_entry.insert("1.0", tmp_file_path) + extension.file_entry.insert("1.0", str(tmp_file_path)) # Invoke the generate button extension.root.nametowidget("generate").invoke() @@ -105,7 +98,7 @@ def test_push_excitation_3dl_generate_button(local_scratch, desktop): finally: # Clean up temporary file - if os.path.exists(tmp_file_path): + if tmp_file_path.exists(): os.unlink(tmp_file_path) h3d.close_project(h3d.project_name) @@ -149,10 +142,10 @@ def test_push_excitation_3dl_exceptions(local_scratch, desktop): tmp_file.write('"Time [us]","V(Port1) [mV]"\n') tmp_file.write("0,0\n") tmp_file.write("1e-9,1\n") - tmp_file_path = tmp_file.name + tmp_file_path = Path(tmp_file.name) try: - data = PushExcitation3DLayoutExtensionData(choice="conductor", file_path=tmp_file_path) + data = PushExcitation3DLayoutExtensionData(choice="conductor", file_path=str(tmp_file_path)) with pytest.raises( AEDTRuntimeError, @@ -162,26 +155,20 @@ def test_push_excitation_3dl_exceptions(local_scratch, desktop): finally: # Clean up temporary file - if os.path.exists(tmp_file_path): + if tmp_file_path.exists(): os.unlink(tmp_file_path) q3d_app.close_project(q3d_app.project_name) def test_push_excitation_3dl_with_sinusoidal_input(local_scratch, desktop): """Test HFSS 3D Layout push excitation with sinusoidal data from file.""" - project_path = shutil.copy( - os.path.join( - local_path, - "..", - "general", - "example_models", - "T41", - "test_post_3d_layout_solved_23R2.aedtz", - ), - os.path.join( - local_scratch.path, - "test_post_3d_layout_solved_23R2.aedtz", - ), + project_path = Path( + shutil.copy( + Path( + TESTS_EXTENSIONS_PATH, "..", "general", "example_models", "T41", "test_post_3d_layout_solved_23R2.aedtz" + ), + Path(local_scratch.path, "test_post_3d_layout_solved_23R2.aedtz"), + ) ) h3d = Hfss3dLayout( @@ -191,14 +178,14 @@ def test_push_excitation_3dl_with_sinusoidal_input(local_scratch, desktop): ) # Use the existing sinusoidal CSV file - file_path = os.path.join(local_path, "..", "general", "example_models", "T41", "Sinusoidal.csv") + file_path = Path(TESTS_EXTENSIONS_PATH, "..", "general", "example_models", "T41", "Sinusoidal.csv") # Ensure the file exists - assert os.path.exists(file_path), f"Test file not found: {file_path}" + assert file_path.exists(), f"Test file not found: {file_path}" try: # Test with no choice (empty choice) - data_no_choice = PushExcitation3DLayoutExtensionData(choice="", file_path=file_path) + data_no_choice = PushExcitation3DLayoutExtensionData(choice="", file_path=str(file_path)) # This should raise an error due to empty choice with pytest.raises(AEDTRuntimeError, match="No excitation selected"): @@ -215,7 +202,7 @@ def test_push_excitation_3dl_with_sinusoidal_input(local_scratch, desktop): excitation_name = excitation_names[0] # Test with correct choice - data_correct_choice = PushExcitation3DLayoutExtensionData(choice=excitation_name, file_path=file_path) + data_correct_choice = PushExcitation3DLayoutExtensionData(choice=excitation_name, file_path=str(file_path)) # This should succeed result = main(data_correct_choice) @@ -232,19 +219,13 @@ def test_push_excitation_3dl_with_sinusoidal_input(local_scratch, desktop): def test_push_excitation_3dl_main_function(local_scratch, desktop): """Test the main function directly based on the provided test example.""" - project_path = shutil.copy( - os.path.join( - local_path, - "..", - "general", - "example_models", - "T41", - "test_post_3d_layout_solved_23R2.aedtz", - ), - os.path.join( - local_scratch.path, - "test_post_3d_layout_solved_23R2.aedtz", - ), + project_path = Path( + shutil.copy( + Path( + TESTS_EXTENSIONS_PATH, "..", "general", "example_models", "T41", "test_post_3d_layout_solved_23R2.aedtz" + ), + Path(local_scratch.path, "test_post_3d_layout_solved_23R2.aedtz"), + ) ) h3d = Hfss3dLayout( @@ -253,11 +234,11 @@ def test_push_excitation_3dl_main_function(local_scratch, desktop): port=str(desktop.port), ) - file_path = os.path.join(local_path, "..", "general", "example_models", "T41", "Sinusoidal.csv") + file_path = Path(TESTS_EXTENSIONS_PATH, "..", "general", "example_models", "T41", "Sinusoidal.csv") try: # Test with empty choice - should fail - data_empty_choice = PushExcitation3DLayoutExtensionData(choice="", file_path=file_path) + data_empty_choice = PushExcitation3DLayoutExtensionData(choice="", file_path=str(file_path)) with pytest.raises(AEDTRuntimeError, match="No excitation selected"): main(data_empty_choice) @@ -275,7 +256,7 @@ def test_push_excitation_3dl_main_function(local_scratch, desktop): choice = excitation_names[0] # Test with correct choice - should succeed - data_correct_choice = PushExcitation3DLayoutExtensionData(choice=choice, file_path=file_path) + data_correct_choice = PushExcitation3DLayoutExtensionData(choice=choice, file_path=str(file_path)) assert main(data_correct_choice) h3d.save_project() diff --git a/tests/system/extensions/test_via_clustering.py b/tests/system/extensions/test_via_clustering.py index 060ff1cb4f2..2dfc87360a5 100644 --- a/tests/system/extensions/test_via_clustering.py +++ b/tests/system/extensions/test_via_clustering.py @@ -22,7 +22,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -import os +from pathlib import Path import pytest @@ -32,29 +32,24 @@ from ansys.aedt.core.extensions.hfss3dlayout.via_clustering import main from ansys.aedt.core.generic.settings import is_linux from ansys.aedt.core.internal.errors import AEDTRuntimeError -from tests.system.extensions.conftest import local_path as extensions_local_path +from tests import TESTS_EXTENSIONS_PATH def test_via_clustering_main_function(local_scratch): """Test the main function of the Via Clustering extension.""" # Copy test model to scratch directory - file_path = os.path.join(local_scratch.path, "test_via_merging.aedb") - new_file = os.path.join(local_scratch.path, "new_test_via_merging.aedb") + file_path = Path(local_scratch.path) / "test_via_merging.aedb" + new_file = Path(local_scratch.path) / "new_test_via_merging.aedb" local_scratch.copyfolder( - os.path.join( - extensions_local_path, - "example_models", - "T45", - "test_via_merging.aedb", - ), + Path(TESTS_EXTENSIONS_PATH) / "example_models" / "T45" / "test_via_merging.aedb", file_path, ) # Create test data following the reference pattern data = ViaClusteringExtensionData( - aedb_path=file_path, + aedb_path=str(file_path), design_name="test", - new_aedb_path=new_file, + new_aedb_path=str(new_file), start_layer="TOP", stop_layer="INT5", contour_list=[ @@ -71,21 +66,16 @@ def test_via_clustering_main_function(local_scratch): assert main(data) # Verify the new AEDB file was created - assert os.path.exists(new_file) + assert new_file.exists() @pytest.mark.skipif(is_linux, reason="Not supported in Linux.") def test_via_clustering_extension_ui(add_app, local_scratch): """Test the Via Clustering extension UI components.""" # Copy the test model to scratch directory - file_path = os.path.join(local_scratch.path, "test_via_merging.aedb") + file_path = Path(local_scratch.path) / "test_via_merging.aedb" local_scratch.copyfolder( - os.path.join( - extensions_local_path, - "example_models", - "T45", - "test_via_merging.aedb", - ), + Path(TESTS_EXTENSIONS_PATH) / "example_models" / "T45" / "test_via_merging.aedb", file_path, ) @@ -149,14 +139,9 @@ def test_via_clustering_exceptions(): def test_via_clustering_button_functions(add_app, local_scratch): """Test the button functions in the Via Clustering extension.""" # Copy the test model to scratch directory - file_path = os.path.join(local_scratch.path, "test_via_merging.aedb") + file_path = Path(local_scratch.path) / "test_via_merging.aedb" local_scratch.copyfolder( - os.path.join( - extensions_local_path, - "example_models", - "T45", - "test_via_merging.aedb", - ), + Path(TESTS_EXTENSIONS_PATH) / "example_models" / "T45" / "test_via_merging.aedb", file_path, ) diff --git a/tests/system/extensions/test_via_design.py b/tests/system/extensions/test_via_design.py index db9609700a9..ae5a679d903 100644 --- a/tests/system/extensions/test_via_design.py +++ b/tests/system/extensions/test_via_design.py @@ -30,7 +30,7 @@ from ansys.aedt.core.extensions.hfss3dlayout.via_design import EXPORT_EXAMPLES from ansys.aedt.core.extensions.hfss3dlayout.via_design import ViaDesignExtension from ansys.aedt.core.generic.settings import is_linux -from tests.system.extensions.conftest import config +from tests.conftest import config @pytest.mark.skipif( diff --git a/tests/system/filter_solutions/conftest.py b/tests/system/filter_solutions/conftest.py deleted file mode 100644 index 6e2a2e1549d..00000000000 --- a/tests/system/filter_solutions/conftest.py +++ /dev/null @@ -1,161 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -""" -Unit Test Configuration Module -------------------------------- - -Description -=========== - -This module contains the configuration and fixture for the pytest-based unit tests for PyAEDT. - -The default configuration can be changed by placing a file called local_config.json in the same -directory as this module. An example of the contents of local_config.json -{ - "desktopVersion": "2022.2", - "NonGraphical": false, - "NewThread": false, - "skip_desktop_test": false -} - -""" - -import json -import os -import random -import shutil -import string -import sys -import tempfile - -import pytest - -from ansys.aedt.core.aedt_logger import pyaedt_logger -from ansys.aedt.core.filtersolutions import DistributedDesign -from ansys.aedt.core.filtersolutions import LumpedDesign -from ansys.aedt.core.generic.settings import settings -from ansys.aedt.core.internal.filesystem import Scratch - -settings.enable_local_log_file = False -settings.enable_global_log_file = False -settings.number_of_grpc_api_retries = 6 -settings.retry_n_times_time_interval = 0.5 -settings.enable_error_handler = False -settings.enable_desktop_logs = False -settings.desktop_launch_timeout = 180 -settings.release_on_exception = False -settings.wait_for_license = True -settings.enable_pandas_output = True - -local_path = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(local_path) - -# Initialize default desktop configuration -default_version = "2025.2" - -config = { - "desktopVersion": default_version, - "NonGraphical": True, - "NewThread": True, - "skip_desktop_test": False, - "build_machine": True, - "skip_space_claim": False, - "skip_circuits": False, - "skip_edb": False, - "skip_debug": False, - "skip_modelithics": True, - "local": False, - "use_grpc": True, - "disable_sat_bounding_box": True, - "local_example_folder": None, - "use_local_example_data": False, -} - -# Check for the local config file, override defaults if found -local_config_file = os.path.join(local_path, "local_config.json") -if os.path.exists(local_config_file): - try: - with open(local_config_file) as f: - local_config = json.load(f) - except Exception: # pragma: no cover - local_config = {} - config.update(local_config) - -NONGRAPHICAL = config["NonGraphical"] -settings.disable_bounding_box_sat = config["disable_sat_bounding_box"] -desktop_version = config["desktopVersion"] -new_thread = config["NewThread"] -settings.use_grpc_api = config["use_grpc"] -settings.local_example_folder = config["local_example_folder"] - -logger = pyaedt_logger - - -def generate_random_string(length): - characters = string.ascii_letters + string.digits - random_string = "".join(random.sample(characters, length)) - return random_string - - -def generate_random_ident(): - ident = "-" + generate_random_string(6) + "-" + generate_random_string(6) + "-" + generate_random_string(6) - return ident - - -@pytest.fixture(scope="session", autouse=True) -def init_scratch(): - test_folder_name = "unit_test" + generate_random_ident() - test_folder = os.path.join(tempfile.gettempdir(), test_folder_name) - try: - os.makedirs(test_folder, mode=0o777) - except FileExistsError as e: - print(f"Failed to create {test_folder}. Reason: {e}") - - yield test_folder - - try: - shutil.rmtree(test_folder, ignore_errors=True) - except Exception as e: - print(f"Failed to delete {test_folder}. Reason: {e}") - - -@pytest.fixture(scope="module", autouse=True) -def local_scratch(init_scratch): - tmp_path = init_scratch - scratch = Scratch(tmp_path) - yield scratch - scratch.remove() - - -@pytest.fixture(scope="function") -def lumped_design(): - """Fixture for creating a LumpedDesign object.""" - return LumpedDesign(config["desktopVersion"]) - - -@pytest.fixture(scope="function") -def distributed_design(): - """Fixture for creating a DistributedDesign object.""" - return DistributedDesign(config["desktopVersion"]) diff --git a/tests/system/filter_solutions/test_desktop_types.py b/tests/system/filter_solutions/test_desktop_types.py index 0b09ff6879f..0383c8c95c2 100644 --- a/tests/system/filter_solutions/test_desktop_types.py +++ b/tests/system/filter_solutions/test_desktop_types.py @@ -28,7 +28,7 @@ from ansys.aedt.core import Hfss from ansys.aedt.core import Hfss3dLayout from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config @pytest.mark.skipif(is_linux, reason="FilterSolutions API is not supported on Linux.") diff --git a/tests/system/filter_solutions/test_distributed_filter/test_distributed_geometry.py b/tests/system/filter_solutions/test_distributed_filter/test_distributed_geometry.py index dc407d81e28..41236931185 100644 --- a/tests/system/filter_solutions/test_distributed_filter/test_distributed_geometry.py +++ b/tests/system/filter_solutions/test_distributed_filter/test_distributed_geometry.py @@ -25,7 +25,7 @@ import pytest from ansys.aedt.core.generic.general_methods import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config @pytest.mark.skipif(is_linux, reason="FilterSolutions API is not applicable on Linux.") diff --git a/tests/system/filter_solutions/test_distributed_filter/test_distributed_parasitics.py b/tests/system/filter_solutions/test_distributed_filter/test_distributed_parasitics.py index ad7032749ca..1cdea17ce51 100644 --- a/tests/system/filter_solutions/test_distributed_filter/test_distributed_parasitics.py +++ b/tests/system/filter_solutions/test_distributed_filter/test_distributed_parasitics.py @@ -26,7 +26,7 @@ from ansys.aedt.core.filtersolutions_core.distributed_topology import TopologyType from ansys.aedt.core.generic.general_methods import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config from tests.system.filter_solutions.resources import read_resource_file diff --git a/tests/system/filter_solutions/test_distributed_filter/test_distributed_radial.py b/tests/system/filter_solutions/test_distributed_filter/test_distributed_radial.py index a473539fd62..b0f6dcbf380 100644 --- a/tests/system/filter_solutions/test_distributed_filter/test_distributed_radial.py +++ b/tests/system/filter_solutions/test_distributed_filter/test_distributed_radial.py @@ -25,7 +25,7 @@ import pytest from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config @pytest.mark.skipif(is_linux, reason="FilterSolutions API is not applicable on Linux.") diff --git a/tests/system/filter_solutions/test_distributed_filter/test_distributed_substrate.py b/tests/system/filter_solutions/test_distributed_filter/test_distributed_substrate.py index 9d249913a36..d5c0cb0a2bf 100644 --- a/tests/system/filter_solutions/test_distributed_filter/test_distributed_substrate.py +++ b/tests/system/filter_solutions/test_distributed_filter/test_distributed_substrate.py @@ -28,7 +28,7 @@ from ansys.aedt.core.filtersolutions_core.export_to_aedt import SubstrateResistivity from ansys.aedt.core.filtersolutions_core.export_to_aedt import SubstrateType from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config @pytest.mark.skipif(is_linux, reason="FilterSolutions API is not supported on Linux.") diff --git a/tests/system/filter_solutions/test_distributed_filter/test_distributed_topology.py b/tests/system/filter_solutions/test_distributed_filter/test_distributed_topology.py index af60af7b43d..77fb5a91732 100644 --- a/tests/system/filter_solutions/test_distributed_filter/test_distributed_topology.py +++ b/tests/system/filter_solutions/test_distributed_filter/test_distributed_topology.py @@ -29,7 +29,7 @@ from ansys.aedt.core.filtersolutions_core.distributed_topology import TapPosition from ansys.aedt.core.filtersolutions_core.distributed_topology import TopologyType from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config from tests.system.filter_solutions.resources import read_resource_file diff --git a/tests/system/filter_solutions/test_export_to_aedt/test_export_to_aedt.py b/tests/system/filter_solutions/test_export_to_aedt/test_export_to_aedt.py index 8edaa24bc0e..25904d3477f 100644 --- a/tests/system/filter_solutions/test_export_to_aedt/test_export_to_aedt.py +++ b/tests/system/filter_solutions/test_export_to_aedt/test_export_to_aedt.py @@ -33,7 +33,7 @@ from ansys.aedt.core.filtersolutions_core.export_to_aedt import SubstrateResistivity from ansys.aedt.core.filtersolutions_core.export_to_aedt import SubstrateType from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config from tests.system.filter_solutions.resources import read_resource_file from tests.system.filter_solutions.resources import resource_path diff --git a/tests/system/filter_solutions/test_export_to_aedt/test_optimization_goals_table.py b/tests/system/filter_solutions/test_export_to_aedt/test_optimization_goals_table.py index 9a77ec4de5f..cd76a4d4f27 100644 --- a/tests/system/filter_solutions/test_export_to_aedt/test_optimization_goals_table.py +++ b/tests/system/filter_solutions/test_export_to_aedt/test_optimization_goals_table.py @@ -27,7 +27,7 @@ from ansys.aedt.core.filtersolutions_core.optimization_goals_table import OptimizationGoalParameter from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config from tests.system.filter_solutions.resources import resource_path diff --git a/tests/system/filter_solutions/test_filter/test_attributes.py b/tests/system/filter_solutions/test_filter/test_attributes.py index 0dd71f15071..66a591f6fc0 100644 --- a/tests/system/filter_solutions/test_filter/test_attributes.py +++ b/tests/system/filter_solutions/test_filter/test_attributes.py @@ -37,7 +37,7 @@ from ansys.aedt.core.filtersolutions_core.attributes import SinglePointRippleInfZeros from ansys.aedt.core.filtersolutions_core.attributes import StopbandDefinition from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config default_center_freq = "1G" changed_freq = "500M" diff --git a/tests/system/filter_solutions/test_filter/test_dll_interface.py b/tests/system/filter_solutions/test_filter/test_dll_interface.py index 09911f62629..6f7bdf7b753 100644 --- a/tests/system/filter_solutions/test_filter/test_dll_interface.py +++ b/tests/system/filter_solutions/test_filter/test_dll_interface.py @@ -31,7 +31,7 @@ import ansys.aedt.core.filtersolutions_core from ansys.aedt.core.filtersolutions_core.attributes import FilterType from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config from tests.system.filter_solutions.test_filter import test_transmission_zeros diff --git a/tests/system/filter_solutions/test_filter/test_graph_setup.py b/tests/system/filter_solutions/test_filter/test_graph_setup.py index d279f5dbd90..b8ee89eae2c 100644 --- a/tests/system/filter_solutions/test_filter/test_graph_setup.py +++ b/tests/system/filter_solutions/test_filter/test_graph_setup.py @@ -25,7 +25,7 @@ import pytest from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config @pytest.mark.skipif(is_linux, reason="FilterSolutions API is not supported on Linux.") diff --git a/tests/system/filter_solutions/test_filter/test_ideal_response.py b/tests/system/filter_solutions/test_filter/test_ideal_response.py index cc507bd0910..172910851ed 100644 --- a/tests/system/filter_solutions/test_filter/test_ideal_response.py +++ b/tests/system/filter_solutions/test_filter/test_ideal_response.py @@ -30,7 +30,7 @@ from ansys.aedt.core.filtersolutions_core.ideal_response import SParametersResponseColumn from ansys.aedt.core.filtersolutions_core.ideal_response import TimeResponseColumn from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config from tests.system.filter_solutions.resources import read_resource_file diff --git a/tests/system/filter_solutions/test_filter/test_multiple_bands_table.py b/tests/system/filter_solutions/test_filter/test_multiple_bands_table.py index 3c20a680f27..caf371601bd 100644 --- a/tests/system/filter_solutions/test_filter/test_multiple_bands_table.py +++ b/tests/system/filter_solutions/test_filter/test_multiple_bands_table.py @@ -25,7 +25,7 @@ import pytest from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config @pytest.mark.skipif(is_linux, reason="FilterSolutions API is not supported on Linux.") diff --git a/tests/system/filter_solutions/test_filter/test_transmission_zeros.py b/tests/system/filter_solutions/test_filter/test_transmission_zeros.py index abc734cc25b..7758f37fdd0 100644 --- a/tests/system/filter_solutions/test_filter/test_transmission_zeros.py +++ b/tests/system/filter_solutions/test_filter/test_transmission_zeros.py @@ -25,7 +25,7 @@ import pytest from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config @pytest.mark.skipif(is_linux, reason="FilterSolutions API is not supported on Linux.") diff --git a/tests/system/filter_solutions/test_lumped_filter/test_lumped_nodes_and_leads.py b/tests/system/filter_solutions/test_lumped_filter/test_lumped_nodes_and_leads.py index 9b5c26344c4..ba6fd6547d9 100644 --- a/tests/system/filter_solutions/test_lumped_filter/test_lumped_nodes_and_leads.py +++ b/tests/system/filter_solutions/test_lumped_filter/test_lumped_nodes_and_leads.py @@ -25,7 +25,7 @@ import pytest from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config from tests.system.filter_solutions.resources import read_resource_file diff --git a/tests/system/filter_solutions/test_lumped_filter/test_lumped_parasitics.py b/tests/system/filter_solutions/test_lumped_filter/test_lumped_parasitics.py index 6cb0e55a84d..cce59769e39 100644 --- a/tests/system/filter_solutions/test_lumped_filter/test_lumped_parasitics.py +++ b/tests/system/filter_solutions/test_lumped_filter/test_lumped_parasitics.py @@ -25,7 +25,7 @@ import pytest from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config from tests.system.filter_solutions.resources import read_resource_file diff --git a/tests/system/filter_solutions/test_lumped_filter/test_lumped_termination_impedance_table.py b/tests/system/filter_solutions/test_lumped_filter/test_lumped_termination_impedance_table.py index a7ddb7b1eb6..a6c95424b57 100644 --- a/tests/system/filter_solutions/test_lumped_filter/test_lumped_termination_impedance_table.py +++ b/tests/system/filter_solutions/test_lumped_filter/test_lumped_termination_impedance_table.py @@ -27,7 +27,7 @@ from ansys.aedt.core.filtersolutions_core.lumped_termination_impedance_table import ComplexReactanceType from ansys.aedt.core.filtersolutions_core.lumped_termination_impedance_table import ComplexTerminationDefinition from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config @pytest.mark.skipif(is_linux, reason="FilterSolutions API is not supported on Linux.") diff --git a/tests/system/filter_solutions/test_lumped_filter/test_lumped_topology.py b/tests/system/filter_solutions/test_lumped_filter/test_lumped_topology.py index 083b50eab3a..bb1b8c1eb33 100644 --- a/tests/system/filter_solutions/test_lumped_filter/test_lumped_topology.py +++ b/tests/system/filter_solutions/test_lumped_filter/test_lumped_topology.py @@ -28,7 +28,7 @@ from ansys.aedt.core.filtersolutions_core.attributes import FilterClass from ansys.aedt.core.filtersolutions_core.attributes import FilterType from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config from tests.system.filter_solutions.resources import read_resource_file diff --git a/tests/system/filter_solutions/test_raise_error.py b/tests/system/filter_solutions/test_raise_error.py index 20d1590a38f..f6dfc9016c6 100644 --- a/tests/system/filter_solutions/test_raise_error.py +++ b/tests/system/filter_solutions/test_raise_error.py @@ -25,7 +25,7 @@ import pytest from ansys.aedt.core.generic.settings import is_linux -from tests.system.filter_solutions.conftest import config +from tests.conftest import config from tests.system.filter_solutions.test_filter import test_transmission_zeros diff --git a/tests/system/general/conftest.py b/tests/system/general/conftest.py index 3eef1b28461..7e31d723300 100644 --- a/tests/system/general/conftest.py +++ b/tests/system/general/conftest.py @@ -34,102 +34,29 @@ The default configuration can be changed by placing a file called local_config.json in the same directory as this module. An example of the contents of local_config.json { - "desktopVersion": "2022.2", + "desktopVersion": "2025.2", "NonGraphical": false, "NewThread": false, - "skip_desktop_test": false } """ import gc -import json import os -import random -import shutil -import string import sys import tempfile import time import pytest -from ansys.aedt.core import Edb -from ansys.aedt.core import Hfss from ansys.aedt.core.aedt_logger import pyaedt_logger from ansys.aedt.core.desktop import Desktop -from ansys.aedt.core.generic.file_utils import generate_unique_name from ansys.aedt.core.generic.settings import settings from ansys.aedt.core.internal.desktop_sessions import _desktop_sessions -from ansys.aedt.core.internal.filesystem import Scratch -from tests import TESTS_GENERAL_PATH +from tests.conftest import config +from tests.conftest import logger -settings.enable_local_log_file = False -settings.enable_global_log_file = False -settings.number_of_grpc_api_retries = 6 -settings.retry_n_times_time_interval = 0.5 -settings.enable_error_handler = False -settings.enable_desktop_logs = False -settings.desktop_launch_timeout = 180 -settings.release_on_exception = False -settings.wait_for_license = True -settings.enable_pandas_output = True -settings.use_local_example_data = False - -local_path = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(local_path) - -# Initialize default desktop configuration -default_version = "2025.2" - -config = { - "desktopVersion": default_version, - "NonGraphical": True, - "NewThread": True, - "skip_desktop_test": False, - "build_machine": True, - "skip_space_claim": False, - "skip_circuits": False, - "skip_edb": False, - "skip_debug": False, - "local": False, - "use_grpc": True, - "disable_sat_bounding_box": True, - "use_local_example_data": False, -} - -# Check for the local config file, override defaults if found -local_config_file = os.path.join(local_path, "local_config.json") -if os.path.exists(local_config_file): - try: - with open(local_config_file) as f: - local_config = json.load(f) - except Exception: # pragma: no cover - local_config = {} - config.update(local_config) - -NONGRAPHICAL = config["NonGraphical"] -settings.disable_bounding_box_sat = config["disable_sat_bounding_box"] -desktop_version = config["desktopVersion"] -new_thread = config["NewThread"] -settings.use_grpc_api = config["use_grpc"] settings.objects_lazy_load = False -settings.use_local_example_data = config["use_local_example_data"] -if settings.use_local_example_data: - settings.local_example_folder = config["local_example_folder"] - -logger = pyaedt_logger - - -def generate_random_string(length): - characters = string.ascii_letters + string.digits - random_string = "".join(random.sample(characters, length)) - return random_string - - -def generate_random_ident(): - ident = "-" + generate_random_string(6) + "-" + generate_random_string(6) + "-" + generate_random_string(6) - return ident def _delete_objects(): @@ -142,41 +69,16 @@ def _delete_objects(): gc.collect() -@pytest.fixture(scope="session", autouse=True) -def init_scratch(): - test_folder_name = "unit_test" + generate_random_ident() - test_folder = os.path.join(tempfile.gettempdir(), test_folder_name) - try: - os.makedirs(test_folder, mode=0o777) - except FileExistsError as e: - print(f"Failed to create {test_folder}. Reason: {e}") - - yield test_folder - - try: - shutil.rmtree(test_folder, ignore_errors=True) - except Exception as e: - print(f"Failed to delete {test_folder}. Reason: {e}") - - -@pytest.fixture(scope="module", autouse=True) -def local_scratch(init_scratch): - tmp_path = init_scratch - scratch = Scratch(tmp_path) - yield scratch - scratch.remove() - - @pytest.fixture(scope="module", autouse=True) def desktop(): _delete_objects() keys = list(_desktop_sessions.keys()) for key in keys: del _desktop_sessions[key] - d = Desktop(desktop_version, NONGRAPHICAL, new_thread) + d = Desktop(config["desktopVersion"], config["NonGraphical"], config["NewThread"]) d.odesktop.SetTempDirectory(tempfile.gettempdir()) d.disable_autosave() - if desktop_version > "2022.2": + if config["desktopVersion"] > "2022.2": d.odesktop.SetDesktopConfiguration("All") d.odesktop.SetSchematicEnvironment(0) yield d @@ -187,78 +89,3 @@ def desktop(): os.kill(pid, 9) except OSError: pass - - -@pytest.fixture(scope="module") -def add_app(local_scratch): - def _method( - project_name=None, design_name=None, solution_type=None, application=None, subfolder="", just_open=False - ): - if project_name and not just_open: - example_project = os.path.join(TESTS_GENERAL_PATH, "example_models", subfolder, project_name + ".aedt") - example_folder = os.path.join(TESTS_GENERAL_PATH, "example_models", subfolder, project_name + ".aedb") - if os.path.exists(example_project): - # Copy unit test project to scratch folder. Return full file path to the project without extension. - test_project = local_scratch.copyfile(example_project) - elif os.path.exists(example_project + "z"): - example_project = example_project + "z" - test_project = local_scratch.copyfile(example_project) - else: - test_project = os.path.join(local_scratch.path, project_name + ".aedt") - if os.path.exists(example_folder): - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") - local_scratch.copyfolder(example_folder, target_folder) - elif project_name and just_open: - test_project = project_name - else: - test_project = None - if not application: - application = Hfss - - args = { - "project": test_project, - "design": design_name, - "version": desktop_version, - "non_graphical": NONGRAPHICAL, - "remove_lock": True, - } - if solution_type: - args["solution_type"] = solution_type - return application(**args) - - return _method - - -@pytest.fixture(scope="module") -def test_project_file(local_scratch): - def _method(project_name=None, subfolder=None): - if subfolder: - project_file = os.path.join(TESTS_GENERAL_PATH, "example_models", subfolder, project_name + ".aedt") - else: - project_file = os.path.join(local_scratch.path, project_name + ".aedt") - if os.path.exists(project_file): - return project_file - else: - return None - - return _method - - -@pytest.fixture(scope="module") -def add_edb(local_scratch): - def _method(project_name=None, subfolder=""): - if project_name: - example_folder = os.path.join(TESTS_GENERAL_PATH, "example_models", subfolder, project_name + ".aedb") - if os.path.exists(example_folder): - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") - local_scratch.copyfolder(example_folder, target_folder) - else: - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") - else: - target_folder = os.path.join(local_scratch.path, generate_unique_name("TestEdb") + ".aedb") - return Edb( - target_folder, - edbversion=desktop_version, - ) - - return _method diff --git a/tests/system/general/test_01_3dlayout_edb.py b/tests/system/general/test_01_3dlayout_edb.py index 5d87f2eb7c9..3aa2e729bc1 100644 --- a/tests/system/general/test_01_3dlayout_edb.py +++ b/tests/system/general/test_01_3dlayout_edb.py @@ -30,7 +30,7 @@ from ansys.aedt.core import Hfss3dLayout from ansys.aedt.core.modeler.pcb.object_3d_layout import Components3DLayout from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test_subfolder = "T40" original_project_name = "ANSYS-HSD_V1" diff --git a/tests/system/general/test_01_Design.py b/tests/system/general/test_01_Design.py index 35bddbae88a..afe7d08cb41 100644 --- a/tests/system/general/test_01_Design.py +++ b/tests/system/general/test_01_Design.py @@ -37,8 +37,8 @@ from ansys.aedt.core.generic.general_methods import is_linux from ansys.aedt.core.generic.general_methods import settings from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config -from tests.system.general.conftest import desktop_version +from tests.conftest import config +from tests.conftest import desktop_version test_subfolder = "T01" if config["desktopVersion"] > "2022.2": diff --git a/tests/system/general/test_01_configuration_files.py b/tests/system/general/test_01_configuration_files.py index 10afac99ebf..4fd8a40db9e 100644 --- a/tests/system/general/test_01_configuration_files.py +++ b/tests/system/general/test_01_configuration_files.py @@ -33,7 +33,7 @@ from ansys.aedt.core import Q2d from ansys.aedt.core import Q3d from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test_project_name = "dm boundary test" test_field_name = "Potter_Horn" diff --git a/tests/system/general/test_02_3D_modeler.py b/tests/system/general/test_02_3D_modeler.py index a3ee128cf4a..02da82e08a9 100644 --- a/tests/system/general/test_02_3D_modeler.py +++ b/tests/system/general/test_02_3D_modeler.py @@ -37,7 +37,7 @@ from ansys.aedt.core.modeler.cad.primitives import CoordinateSystem as cs from ansys.aedt.core.modeler.cad.primitives import PolylineSegment from ansys.aedt.core.modeler.geometry_operators import GeometryOperators as go -from tests.system.general.conftest import config +from tests.conftest import config test_subfolder = "T02" if config["desktopVersion"] > "2022.2": diff --git a/tests/system/general/test_03_Materials.py b/tests/system/general/test_03_Materials.py index 91d5627e212..b19e92a71ba 100644 --- a/tests/system/general/test_03_Materials.py +++ b/tests/system/general/test_03_Materials.py @@ -35,7 +35,7 @@ from ansys.aedt.core.modules.material import MatProperties from ansys.aedt.core.modules.material import SurfMatProperties from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test_subfolder = "T03" diff --git a/tests/system/general/test_04_SBR.py b/tests/system/general/test_04_SBR.py index 5bdca9e0012..2dbd809695a 100644 --- a/tests/system/general/test_04_SBR.py +++ b/tests/system/general/test_04_SBR.py @@ -35,7 +35,7 @@ from ansys.aedt.core.generic.settings import is_linux from ansys.aedt.core.internal.errors import AEDTRuntimeError from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import desktop_version +from tests.conftest import desktop_version if desktop_version > "2022.2": test_project_name = "Cassegrain_231" diff --git a/tests/system/general/test_05_Mesh.py b/tests/system/general/test_05_Mesh.py index e0cf4e5296a..e60b54c29ac 100644 --- a/tests/system/general/test_05_Mesh.py +++ b/tests/system/general/test_05_Mesh.py @@ -26,8 +26,8 @@ from ansys.aedt.core import Maxwell3d from ansys.aedt.core.generic.constants import Plane -from tests.system.general.conftest import config -from tests.system.general.conftest import desktop_version +from tests.conftest import config +from tests.conftest import desktop_version @pytest.fixture(scope="class") diff --git a/tests/system/general/test_06_MessageManager.py b/tests/system/general/test_06_MessageManager.py index c3bfe844b79..2fd35db7c66 100644 --- a/tests/system/general/test_06_MessageManager.py +++ b/tests/system/general/test_06_MessageManager.py @@ -30,7 +30,7 @@ from ansys.aedt.core import Icepak from ansys.aedt.core.aedt_logger import AedtLogger from ansys.aedt.core.generic.settings import settings -from tests.system.general.conftest import config +from tests.conftest import config LOGGER = logging.getLogger(__name__) diff --git a/tests/system/general/test_08_Primitives3D.py b/tests/system/general/test_08_Primitives3D.py index 6f6fb890022..5fe65d0288d 100644 --- a/tests/system/general/test_08_Primitives3D.py +++ b/tests/system/general/test_08_Primitives3D.py @@ -40,7 +40,7 @@ from ansys.aedt.core.modeler.cad.primitives import PolylineSegment from ansys.aedt.core.modeler.geometry_operators import GeometryOperators from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test = sys.modules.keys() diff --git a/tests/system/general/test_09_VariableManager.py b/tests/system/general/test_09_VariableManager.py index f0e6fb22d73..454e20705ef 100644 --- a/tests/system/general/test_09_VariableManager.py +++ b/tests/system/general/test_09_VariableManager.py @@ -32,7 +32,7 @@ from ansys.aedt.core.generic.numbers_utils import decompose_variable_value from ansys.aedt.core.generic.numbers_utils import is_close from ansys.aedt.core.modeler.geometry_operators import GeometryOperators -from tests.system.general.conftest import desktop_version +from tests.conftest import desktop_version @pytest.fixture(scope="class") diff --git a/tests/system/general/test_11_Setup.py b/tests/system/general/test_11_Setup.py index ebeefd625b3..d9caa52ab68 100644 --- a/tests/system/general/test_11_Setup.py +++ b/tests/system/general/test_11_Setup.py @@ -28,7 +28,7 @@ from ansys.aedt.core import Circuit from ansys.aedt.core.generic.constants import Setups -from tests.system.general.conftest import desktop_version +from tests.conftest import desktop_version test_subfolder = "T11" if desktop_version > "2022.2": diff --git a/tests/system/general/test_13_LoadAEDTFile.py b/tests/system/general/test_13_LoadAEDTFile.py index 97d5956d9ee..8f6ae3ffe34 100644 --- a/tests/system/general/test_13_LoadAEDTFile.py +++ b/tests/system/general/test_13_LoadAEDTFile.py @@ -32,7 +32,7 @@ from ansys.aedt.core.internal.load_aedt_file import load_entire_aedt_file from ansys.aedt.core.internal.load_aedt_file import load_keyword_in_aedt_file from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test_subfolder = "T13" if config["desktopVersion"] > "2022.2": diff --git a/tests/system/general/test_14_AedtLogger.py b/tests/system/general/test_14_AedtLogger.py index 47f03a8119b..fb1a0bb0fca 100644 --- a/tests/system/general/test_14_AedtLogger.py +++ b/tests/system/general/test_14_AedtLogger.py @@ -34,7 +34,7 @@ from ansys.aedt.core.aedt_logger import AedtLogger from ansys.aedt.core.generic.settings import settings -from tests.system.general.conftest import config +from tests.conftest import config settings.enable_desktop_logs = True diff --git a/tests/system/general/test_20_HFSS.py b/tests/system/general/test_20_HFSS.py index 51d9486b487..9d68851c391 100644 --- a/tests/system/general/test_20_HFSS.py +++ b/tests/system/general/test_20_HFSS.py @@ -36,8 +36,8 @@ from ansys.aedt.core.visualization.advanced.misc import convert_nearfield_data from tests import TESTS_GENERAL_PATH from tests import TESTS_SOLVERS_PATH -from tests.system.general.conftest import config -from tests.system.general.conftest import settings +from tests.conftest import config +from tests.conftest import settings small_number = 1e-10 # Used for checking equivalence. diff --git a/tests/system/general/test_21_Circuit.py b/tests/system/general/test_21_Circuit.py index bca7492e4d0..648ad5f4d6e 100644 --- a/tests/system/general/test_21_Circuit.py +++ b/tests/system/general/test_21_Circuit.py @@ -33,7 +33,7 @@ from ansys.aedt.core.generic.settings import is_linux from ansys.aedt.core.internal.errors import AEDTRuntimeError from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test_subfolder = "T21" diff --git a/tests/system/general/test_22_Circuit_DynamicLink.py b/tests/system/general/test_22_Circuit_DynamicLink.py index f1ba6b74725..3a869551dfc 100644 --- a/tests/system/general/test_22_Circuit_DynamicLink.py +++ b/tests/system/general/test_22_Circuit_DynamicLink.py @@ -31,7 +31,7 @@ from ansys.aedt.core import Q3d from ansys.aedt.core.generic.settings import is_linux from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test_subfloder = "T22" test_project_name = "Dynamic_Link" diff --git a/tests/system/general/test_27_Maxwell2D.py b/tests/system/general/test_27_Maxwell2D.py index f924bc57f49..97bc4edb170 100644 --- a/tests/system/general/test_27_Maxwell2D.py +++ b/tests/system/general/test_27_Maxwell2D.py @@ -33,7 +33,7 @@ from ansys.aedt.core.generic.constants import SolutionsMaxwell2D from ansys.aedt.core.internal.errors import AEDTRuntimeError from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test_subfolder = "TMaxwell" diff --git a/tests/system/general/test_28_Maxwell3D.py b/tests/system/general/test_28_Maxwell3D.py index 8ef53537d4e..aac6be6f16d 100644 --- a/tests/system/general/test_28_Maxwell3D.py +++ b/tests/system/general/test_28_Maxwell3D.py @@ -37,8 +37,8 @@ from ansys.aedt.core.internal.errors import AEDTRuntimeError from ansys.aedt.core.modeler.geometry_operators import GeometryOperators from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config -from tests.system.solvers.conftest import desktop_version +from tests.conftest import config +from tests.conftest import desktop_version try: from IPython.display import Image diff --git a/tests/system/general/test_30_Q2D.py b/tests/system/general/test_30_Q2D.py index a4b2e195b0d..e145af36b87 100644 --- a/tests/system/general/test_30_Q2D.py +++ b/tests/system/general/test_30_Q2D.py @@ -31,7 +31,7 @@ from ansys.aedt.core.generic.constants import MatrixOperationsQ2D from ansys.aedt.core.internal.errors import AEDTRuntimeError from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test_project_name = "coax_Q2D" test_subfolder = "T30" diff --git a/tests/system/general/test_34_TwinBuilder.py b/tests/system/general/test_34_TwinBuilder.py index cb836af1b63..f2da2790208 100644 --- a/tests/system/general/test_34_TwinBuilder.py +++ b/tests/system/general/test_34_TwinBuilder.py @@ -31,10 +31,10 @@ from ansys.aedt.core import TwinBuilder from ansys.aedt.core.generic.general_methods import is_linux from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import NONGRAPHICAL -from tests.system.general.conftest import config -from tests.system.general.conftest import desktop_version -from tests.system.general.conftest import new_thread +from tests.conftest import NONGRAPHICAL +from tests.conftest import config +from tests.conftest import desktop_version +from tests.conftest import new_thread test_subfolder = "T34" diff --git a/tests/system/general/test_36_Q2D_PostProcessing.py b/tests/system/general/test_36_Q2D_PostProcessing.py index f7eb52e65f1..127223be3c6 100644 --- a/tests/system/general/test_36_Q2D_PostProcessing.py +++ b/tests/system/general/test_36_Q2D_PostProcessing.py @@ -27,7 +27,7 @@ import pytest from ansys.aedt.core import Q2d -from tests.system.general.conftest import config +from tests.conftest import config test_subfolder = "T36" diff --git a/tests/system/general/test_41_3dlayout_modeler.py b/tests/system/general/test_41_3dlayout_modeler.py index edce7435849..72bf86800f7 100644 --- a/tests/system/general/test_41_3dlayout_modeler.py +++ b/tests/system/general/test_41_3dlayout_modeler.py @@ -36,7 +36,7 @@ from ansys.aedt.core.generic.general_methods import is_linux from ansys.aedt.core.visualization.plot.pdf import AnsysReport from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test_subfolder = "T41" test_project_name = "Test_RadioBoard" diff --git a/tests/system/general/test_43_CableModeling.py b/tests/system/general/test_43_CableModeling.py index 09e39183c49..c12a4f8575d 100644 --- a/tests/system/general/test_43_CableModeling.py +++ b/tests/system/general/test_43_CableModeling.py @@ -29,7 +29,7 @@ from ansys.aedt.core.generic.file_utils import read_json from ansys.aedt.core.modules.cable_modeling import Cable from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config if config["desktopVersion"] > "2022.2": project_name = "cable_modeling_231" diff --git a/tests/system/general/test_47_CircuitNetlist.py b/tests/system/general/test_47_CircuitNetlist.py index e4d80ed75a0..6da92f1629d 100644 --- a/tests/system/general/test_47_CircuitNetlist.py +++ b/tests/system/general/test_47_CircuitNetlist.py @@ -28,7 +28,7 @@ from ansys.aedt.core import CircuitNetlist from ansys.aedt.core.generic.general_methods import is_linux -from tests.system.general.conftest import config +from tests.conftest import config netlist = "netlist" test_subfolder = "T47" diff --git a/tests/system/general/test_98_Icepak.py b/tests/system/general/test_98_Icepak.py index 6a57af327d4..6874debe50e 100644 --- a/tests/system/general/test_98_Icepak.py +++ b/tests/system/general/test_98_Icepak.py @@ -41,7 +41,7 @@ from ansys.aedt.core.visualization.post.field_data import FolderPlotSettings from ansys.aedt.core.visualization.post.field_data import SpecifiedScale from tests import TESTS_GENERAL_PATH -from tests.system.general.conftest import config +from tests.conftest import config test_subfolder = "T98" board_3dl = "FilterBoard_H3DL" @@ -68,6 +68,8 @@ solution_freq = "2.5GHz" resolution = 2 +on_ci = os.getenv("ON_CI", "false").lower() == "true" + @pytest.fixture(autouse=True) def ipk(add_app, request) -> Icepak: @@ -742,7 +744,7 @@ def test036__check_bounding_box(self, ipk): real_bound = obj_2_bbox assert abs(sum([i - j for i, j in zip(exp_bounding, real_bound)])) < tol - @pytest.mark.skipif(config["build_machine"], reason="Needs Workbench to run.") + @pytest.mark.skipif(on_ci, reason="Needs Workbench to run.") @pytest.mark.parametrize("ipk", [cold_plate], indirect=True) def test037__export_fluent_mesh(self, ipk): assert ipk.get_liquid_objects() == ["Liquid"] diff --git a/tests/system/general/test_launch_desktop.py b/tests/system/general/test_launch_desktop.py index aada6fe505c..9eea30084d5 100644 --- a/tests/system/general/test_launch_desktop.py +++ b/tests/system/general/test_launch_desktop.py @@ -42,13 +42,12 @@ from ansys.aedt.core.generic.constants import SolutionsMechanical from ansys.aedt.core.generic.general_methods import is_linux from ansys.aedt.core.generic.settings import settings -from tests.system.general.conftest import config +from tests.conftest import config settings.lazy_load = False settings.wait_for_license = True -@pytest.mark.skipif(config["skip_desktop_test"], reason="Desktop tests are not selected by default.") class TestClass: def test_run_desktop_mechanical(self): aedtapp = Mechanical(solution_type=SolutionsMechanical.SteadyStateThermal) diff --git a/tests/system/general/test_utils.py b/tests/system/general/test_utils.py index 01ad0ab8132..331603b717c 100644 --- a/tests/system/general/test_utils.py +++ b/tests/system/general/test_utils.py @@ -30,8 +30,11 @@ from ansys.aedt.core.generic.settings import Settings -def test_settings_load_default_yaml(): +def test_settings_load_default_yaml(monkeypatch): """Test loading the default YAML file in docs/source/Resources.""" + # Set PYAEDT_LOCAL_SETTINGS_PATH to default value + monkeypatch.setenv("PYAEDT_LOCAL_SETTINGS_PATH", "") + default_settings = Settings() local_settings = Settings() diff --git a/tests/system/solvers/conftest.py b/tests/system/solvers/conftest.py deleted file mode 100644 index f04e8ecda39..00000000000 --- a/tests/system/solvers/conftest.py +++ /dev/null @@ -1,246 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -""" -Unit Test Configuration Module -------------------------------- - -Description -=========== - -This module contains the configuration and fixture for the pytest-based unit tests for PyAEDT. - -The default configuration can be changed by placing a file called local_config.json in the same -directory as this module. An example of the contents of local_config.json -{ - "desktopVersion": "2022.2", - "NonGraphical": false, - "NewThread": false, - "skip_desktop_test": false -} - -""" - -import json -import os -from pathlib import Path -import random -import shutil -import string -import sys -import tempfile - -import pytest - -from ansys.aedt.core import Desktop -from ansys.aedt.core import Edb -from ansys.aedt.core import Hfss -from ansys.aedt.core.aedt_logger import pyaedt_logger -from ansys.aedt.core.generic.file_utils import generate_unique_name -from ansys.aedt.core.generic.settings import settings -from ansys.aedt.core.internal.filesystem import Scratch - -settings.enable_local_log_file = False -settings.enable_global_log_file = False -settings.number_of_grpc_api_retries = 6 -settings.retry_n_times_time_interval = 0.5 -settings.enable_error_handler = False -settings.enable_desktop_logs = False -settings.desktop_launch_timeout = 180 -settings.release_on_exception = False -settings.wait_for_license = True -settings.enable_pandas_output = True -settings.use_local_example_data = False - -local_path = Path(__file__).parent -sys.path.append(str(local_path)) - -# Initialize default desktop configuration -default_version = "2025.2" - -os.environ["ANSYSEM_FEATURE_SS544753_ICEPAK_VIRTUALMESHREGION_PARADIGM_ENABLE"] = "1" - -config = { - "desktopVersion": default_version, - "NonGraphical": True, - "NewThread": True, - "skip_desktop_test": False, - "build_machine": True, - "skip_space_claim": False, - "skip_circuits": False, - "skip_edb": False, - "skip_debug": False, - "skip_modelithics": True, - "local": False, - "use_grpc": True, - "disable_sat_bounding_box": True, - "close_desktop": True, - "remove_lock": False, - "local_example_folder": None, - "use_local_example_data": False, -} - -# Check for the local config file, override defaults if found -local_config_file = Path(local_path) / "local_config.json" -if local_config_file.exists(): - try: - with open(local_config_file) as f: - local_config = json.load(f) - except Exception: # pragma: no cover - local_config = {} - config.update(local_config) - -NONGRAPHICAL = config["NonGraphical"] -settings.disable_bounding_box_sat = config["disable_sat_bounding_box"] -desktop_version = config["desktopVersion"] -new_thread = config["NewThread"] -settings.use_grpc_api = config["use_grpc"] -close_desktop = config["close_desktop"] -remove_lock = config["remove_lock"] -settings.use_local_example_data = config["use_local_example_data"] -if settings.use_local_example_data: - settings.local_example_folder = config["local_example_folder"] - -logger = pyaedt_logger - - -def generate_random_string(length): - characters = string.ascii_letters + string.digits - random_string = "".join(random.sample(characters, length)) - return random_string - - -def generate_random_ident(): - ident = "-" + generate_random_string(6) + "-" + generate_random_string(6) + "-" + generate_random_string(6) - return ident - - -@pytest.fixture(scope="session", autouse=True) -def init_scratch(): - test_folder_name = "unit_test" + generate_random_ident() - test_folder = Path(tempfile.gettempdir()) / test_folder_name - try: - os.makedirs(test_folder, mode=0o777) - except FileExistsError as e: - print(f"Failed to create {test_folder}. Reason: {e}") - - yield test_folder - - try: - shutil.rmtree(test_folder, ignore_errors=True) - except Exception as e: - print(f"Failed to delete {test_folder}. Reason: {e}") - - -@pytest.fixture(scope="module", autouse=True) -def local_scratch(init_scratch): - tmp_path = init_scratch - scratch = Scratch(tmp_path) - yield scratch - scratch.remove() - - -@pytest.fixture(scope="module", autouse=True) -def desktop(): - d = Desktop(desktop_version, NONGRAPHICAL, new_thread) - d.odesktop.SetTempDirectory(tempfile.gettempdir()) - d.disable_autosave() - - yield d - - if close_desktop: - d.close_desktop() - else: - d.release_desktop(close_projects=True, close_on_exit=False) - - -@pytest.fixture(scope="module") -def add_app(local_scratch): - def _method( - project_name=None, design_name=None, solution_type=None, application=None, subfolder="", just_open=False - ): - if project_name and not just_open: - example_project = Path(local_path) / "example_models" / subfolder / (project_name + ".aedt") - example_folder = Path(local_path) / "example_models" / subfolder / (project_name + ".aedb") - if example_project.exists(): - test_project = local_scratch.copyfile(str(example_project)) - elif example_project.with_suffix(".aedtz").exists(): - example_project = example_project.with_suffix(".aedtz") - test_project = local_scratch.copyfile(str(example_project)) - else: - test_project = Path(local_scratch.path) / (project_name + ".aedt") - if example_folder.exists(): - target_folder = local_scratch.path / (project_name + ".aedb") - local_scratch.copyfolder(example_folder, target_folder) - elif project_name and just_open: - test_project = project_name - else: - test_project = None - if not application: - application = Hfss - return application( - project=test_project, - design=design_name, - solution_type=solution_type, - version=desktop_version, - remove_lock=remove_lock, - non_graphical=NONGRAPHICAL, - ) - - return _method - - -@pytest.fixture(scope="module") -def test_project_file(local_scratch): - def _method(project_name=None, subfolder=None): - if subfolder: - project_file = Path(local_path) / "example_models" / subfolder / (project_name + ".aedt") - else: - project_file = Path(local_scratch.path) / (project_name + ".aedt") - if project_file.exists(): - return project_file - else: - return None - - return _method - - -@pytest.fixture(scope="module") -def add_edb(local_scratch): - def _method(project_name=None, subfolder=""): - if project_name: - example_folder = Path(local_path) / "example_models" / subfolder / (project_name + ".aedb") - if example_folder.exists(): - target_folder = local_scratch.path / (project_name + ".aedb") - local_scratch.copyfolder(example_folder, target_folder) - else: - target_folder = local_scratch.path / (project_name + ".aedb") - else: - target_folder = local_scratch.path / (generate_unique_name("TestEdb") + ".aedb") - return Edb( - target_folder, - edbversion=desktop_version, - ) - - return _method diff --git a/tests/system/solvers/sequential/test_3dlayout_dcir.py b/tests/system/solvers/sequential/test_3dlayout_dcir.py index b7aba1306b8..45c7ad3f22e 100644 --- a/tests/system/solvers/sequential/test_3dlayout_dcir.py +++ b/tests/system/solvers/sequential/test_3dlayout_dcir.py @@ -26,7 +26,7 @@ from ansys.aedt.core import Hfss3dLayout from ansys.aedt.core.generic.settings import is_linux -from tests.system.solvers.conftest import config +from tests.conftest import config test_subfolder = "dcir" original_project_name = "ANSYS-HSD_V1" diff --git a/tests/system/solvers/sequential/test_icepak_3d_component.py b/tests/system/solvers/sequential/test_icepak_3d_component.py index 8109f55a515..235cabaa584 100644 --- a/tests/system/solvers/sequential/test_icepak_3d_component.py +++ b/tests/system/solvers/sequential/test_icepak_3d_component.py @@ -29,7 +29,7 @@ from ansys.aedt.core import Icepak from ansys.aedt.core.generic.constants import Plane from ansys.aedt.core.modules.boundary.layout_boundary import NativeComponentObject -from tests.system.solvers.conftest import config +from tests.conftest import config test_subfolder = "icepak_board" original_project_name = "FilterBoard" diff --git a/tests/system/solvers/test_00_analyze.py b/tests/system/solvers/test_00_analyze.py index a1b308adeca..0778b70e5a4 100644 --- a/tests/system/solvers/test_00_analyze.py +++ b/tests/system/solvers/test_00_analyze.py @@ -41,8 +41,8 @@ from ansys.aedt.core.modules.profile import Profiles from ansys.aedt.core.modules.profile import SimulationProfile from ansys.aedt.core.visualization.post.spisim import SpiSim -from tests.system.solvers.conftest import desktop_version -from tests.system.solvers.conftest import local_path +from tests import TESTS_SOLVERS_PATH +from tests.conftest import desktop_version sbr_platform_name = "satellite_231" icepak_solved_name = "icepak_summary_solved" @@ -263,13 +263,13 @@ def test_hfss_export_results(self, hfss_app, local_scratch): from ansys.aedt.core.generic.file_utils import read_json if desktop_version > "2023.1": - dict_in = read_json(Path(local_path) / "example_models" / test_subfolder / "array_simple_232.json") - dict_in["Circ_Patch_5GHz_232_1"] = Path(local_path) / "example_models" / test_subfolder / component + dict_in = read_json(Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "array_simple_232.json") + dict_in["Circ_Patch_5GHz_232_1"] = Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / component dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz_232_1"} dict_in["cells"][(3, 3)]["rotation"] = 90 else: - dict_in = read_json(Path(local_path) / "example_models" / test_subfolder / "array_simple.json") - dict_in["Circ_Patch_5GHz1"] = Path(local_path) / "example_models" / test_subfolder / component + dict_in = read_json(Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "array_simple.json") + dict_in["Circ_Patch_5GHz1"] = Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / component dict_in["cells"][(3, 3)] = {"name": "Circ_Patch_5GHz1"} dict_in["cells"][(3, 3)]["rotation"] = 90 hfss_app.create_3d_component_array(dict_in) @@ -427,7 +427,7 @@ def test_icepak_export_fld(self, icepak_solved, local_scratch): ) assert fld_file.exists() fld_file_1 = local_scratch.path / "test_fld_1.fld" - sample_points_file = Path(local_path) / "example_models" / test_subfolder / "temp_points.pts" + sample_points_file = Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "temp_points.pts" icepak_solved.available_variations.independent = True icepak_solved.post.export_field_file( quantity="Temp", @@ -616,7 +616,7 @@ def test_compute_com_exported_touchstone(self, circuit_com): assert com def test_compute_com(self, local_scratch): - com_example_file_folder = Path(local_path) / "example_models" / test_subfolder / "com_unit_test_sparam" + com_example_file_folder = Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "com_unit_test_sparam" thru_s4p = local_scratch.copyfile(Path(com_example_file_folder) / "SerDes_Demo_02_Thru.s4p") fext_s4p = local_scratch.copyfile(com_example_file_folder / "FCI_CC_Long_Link_Pair_2_to_Pair_9_FEXT.s4p") next_s4p = local_scratch.copyfile(com_example_file_folder / "FCI_CC_Long_Link_Pair_11_to_Pair_9_NEXT.s4p") @@ -635,7 +635,7 @@ def test_compute_com(self, local_scratch): assert com_0 and com_1 def test_compute_com_parameter_ver_3p4(self, local_scratch): - com_example_file_folder = Path(local_path) / "example_models" / test_subfolder / "com_unit_test_sparam" + com_example_file_folder = Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "com_unit_test_sparam" thru_s4p = local_scratch.copyfile(com_example_file_folder / "SerDes_Demo_02_Thru.s4p") spisim = SpiSim(thru_s4p) @@ -679,7 +679,7 @@ def test_output_variables_3dlayout(self, hfss3dl_solved): def test_spisim_advanced_report_ucie(self, local_scratch): spisim_advanced_report_exmaple_folder = ( - Path(local_path) / "example_models" / test_subfolder / "spisim_advanced_report" + Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "spisim_advanced_report" ) fpath_snp = local_scratch.copyfile(spisim_advanced_report_exmaple_folder / "5_C50.s20p") diff --git a/tests/system/solvers/test_01_pdf.py b/tests/system/solvers/test_01_pdf.py index 69c7fedfd91..d4ad81f8d10 100644 --- a/tests/system/solvers/test_01_pdf.py +++ b/tests/system/solvers/test_01_pdf.py @@ -33,8 +33,8 @@ from ansys.aedt.core.visualization.plot.pdf import AnsysReport from ansys.aedt.core.visualization.post.compliance import VirtualCompliance from ansys.aedt.core.visualization.post.compliance import VirtualComplianceGenerator -from tests.system.solvers.conftest import desktop_version -from tests.system.solvers.conftest import local_path +from tests import TESTS_SOLVERS_PATH +from tests.conftest import desktop_version tol = 1e-12 test_project_name = "ANSYS-HSD_V1_0_test" @@ -44,7 +44,7 @@ @pytest.fixture(scope="class") def aedtapp(add_app): - app = add_app(test_project_name, application=Circuit, subfolder=os.path.join(test_subfolder, "compliance")) + app = add_app(test_project_name, application=Circuit, subfolder=str(Path(test_subfolder) / "compliance")) return app @@ -75,13 +75,16 @@ def test_create_pdf(self, local_scratch): report.add_text("hola", True, True) report.add_empty_line(2) report.add_page_break() - report.add_image(os.path.join(local_path, "example_models", test_subfolder, "Coax_HFSS.jpg"), "Coaxial Cable") + report.add_image( + Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "Coax_HFSS.jpg", "Coaxial Cable" + ) report.add_section(portrait=False, page_format="a3") report.add_table("MyTable", [["x", "y"], ["0", "1"], ["2", "3"], ["10", "20"]]) report.add_section() report.add_chart([0, 1, 2, 3, 4, 5], [10, 20, 4, 30, 40, 12], "Freq", "Val", "MyTable") report.add_toc() - assert os.path.exists(report.save_pdf(local_scratch.path, "my_firstpdf.pdf")) + report.save_pdf(local_scratch.path, "my_firstpdf.pdf") + assert (Path(local_scratch.path) / "my_firstpdf.pdf").exists() def test_create_pdf_schematic(self, circuit_test): report = AnsysReport() @@ -90,24 +93,42 @@ def test_create_pdf_schematic(self, circuit_test): def test_virtual_compliance(self, local_scratch, aedtapp): template = ( - Path(local_path) / "example_models" / test_subfolder / "compliance" / "general_compliance_template.json" + Path(TESTS_SOLVERS_PATH) + / "example_models" + / test_subfolder + / "compliance" + / "general_compliance_template.json" ) template = local_scratch.copyfile(template) local_scratch.copyfile( - Path(local_path) / "example_models" / test_subfolder / "compliance" / "ContourEyeDiagram_Custom.json" + Path(TESTS_SOLVERS_PATH) + / "example_models" + / test_subfolder + / "compliance" + / "ContourEyeDiagram_Custom.json" + ) + local_scratch.copyfile( + Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "compliance" / "spisim_erl.cfg" ) - local_scratch.copyfile(Path(local_path) / "example_models" / test_subfolder / "compliance" / "spisim_erl.cfg") local_scratch.copyfile( - Path(local_path) / "example_models" / test_subfolder / "compliance" / "Sparameter_Custom.json" + Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "compliance" / "Sparameter_Custom.json" ) local_scratch.copyfile( - Path(local_path) / "example_models" / test_subfolder / "compliance" / "Sparameter_Insertion_Custom.json" + Path(TESTS_SOLVERS_PATH) + / "example_models" + / test_subfolder + / "compliance" + / "Sparameter_Insertion_Custom.json" ) local_scratch.copyfile( - Path(local_path) / "example_models" / test_subfolder / "compliance" / "StatisticalEyeDiagram_Custom.json" + Path(TESTS_SOLVERS_PATH) + / "example_models" + / test_subfolder + / "compliance" + / "StatisticalEyeDiagram_Custom.json" ) local_scratch.copyfile( - Path(local_path) / "example_models" / test_subfolder / "compliance" / "EyeDiagram_Custom.json" + Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "compliance" / "EyeDiagram_Custom.json" ) with open(template, "r+") as f: @@ -119,10 +140,10 @@ def test_virtual_compliance(self, local_scratch, aedtapp): compliance_folder = Path(local_scratch.path) / "vc" os.makedirs(compliance_folder, exist_ok=True) vc = VirtualComplianceGenerator("Test_full", "Diff_Via") - vc.dut_image = Path(local_path) / "example_models" / test_subfolder / "nets.jpg" + vc.dut_image = Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "nets.jpg" vc.project_file = aedtapp.project_file vc.add_report_from_folder( - input_folder=Path(local_path) / "example_models" / test_subfolder / "compliance", + input_folder=Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "compliance", design_name="Circuit1", group_plots=True, project=aedtapp.project_file, @@ -146,7 +167,7 @@ def test_virtual_compliance(self, local_scratch, aedtapp): name="ERL", ) local_scratch.copyfile( - Path(local_path) / "example_models" / test_subfolder / "compliance" / "skew.json", + Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "compliance" / "skew.json", Path(compliance_folder) / "skew.json", ) vc.add_report_derived_parameter( @@ -166,7 +187,7 @@ def test_virtual_compliance(self, local_scratch, aedtapp): def test_spisim_raw_read(self, local_scratch): from ansys.aedt.core.visualization.post.spisim import SpiSimRawRead - raw_file = os.path.join(local_path, "example_models", test_subfolder, "SerDes_Demo_02_Thru.s4p_ERL.raw") + raw_file = Path(TESTS_SOLVERS_PATH) / "example_models" / test_subfolder / "SerDes_Demo_02_Thru.s4p_ERL.raw" raw_file = local_scratch.copyfile(raw_file) raw_file = SpiSimRawRead(raw_file) diff --git a/tests/system/visualization/conftest.py b/tests/system/visualization/conftest.py deleted file mode 100644 index 981340392c6..00000000000 --- a/tests/system/visualization/conftest.py +++ /dev/null @@ -1,281 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -""" -Unit Test Configuration Module -------------------------------- - -Description -=========== - -This module contains the configuration and fixture for the pytest-based unit tests for PyAEDT. - -The default configuration can be changed by placing a file called local_config.json in the same -directory as this module. An example of the contents of local_config.json -{ - "desktopVersion": "2022.2", - "NonGraphical": false, - "NewThread": false, - "skip_desktop_test": false -} - -""" - -import gc -import json -import os -import random -import shutil -import string -import sys -import tempfile -import time - -import pytest - -from ansys.aedt.core import Desktop -from ansys.aedt.core import Edb -from ansys.aedt.core import Hfss -from ansys.aedt.core.aedt_logger import pyaedt_logger -from ansys.aedt.core.filtersolutions import DistributedDesign -from ansys.aedt.core.filtersolutions import LumpedDesign -from ansys.aedt.core.generic.file_utils import generate_unique_name -from ansys.aedt.core.generic.settings import settings -from ansys.aedt.core.internal.desktop_sessions import _desktop_sessions -from ansys.aedt.core.internal.filesystem import Scratch -from tests import TESTS_VISUALIZATION_PATH - -settings.enable_local_log_file = False -settings.enable_global_log_file = False -settings.number_of_grpc_api_retries = 6 -settings.retry_n_times_time_interval = 0.5 -settings.enable_error_handler = False -settings.enable_desktop_logs = False -settings.desktop_launch_timeout = 180 -settings.release_on_exception = False -settings.wait_for_license = True -settings.enable_pandas_output = True -settings.use_local_example_data = False - -local_path = os.path.dirname(os.path.realpath(__file__)) -sys.path.append(local_path) - -# Initialize default desktop configuration -default_version = "2025.2" - -os.environ["ANSYSEM_FEATURE_SS544753_ICEPAK_VIRTUALMESHREGION_PARADIGM_ENABLE"] = "1" - -config = { - "desktopVersion": default_version, - "NonGraphical": True, - "NewThread": True, - "skip_desktop_test": False, - "build_machine": True, - "skip_space_claim": False, - "skip_circuits": False, - "skip_edb": False, - "skip_debug": False, - "local": False, - "use_grpc": True, - "disable_sat_bounding_box": True, - "use_local_example_data": False, - "close_desktop": True, -} - -# Check for the local config file, override defaults if found -local_config_file = os.path.join(local_path, "local_config.json") -if os.path.exists(local_config_file): - try: - with open(local_config_file) as f: - local_config = json.load(f) - except Exception: # pragma: no cover - local_config = {} - config.update(local_config) - -NONGRAPHICAL = config["NonGraphical"] -settings.disable_bounding_box_sat = config["disable_sat_bounding_box"] -desktop_version = config["desktopVersion"] -new_thread = config["NewThread"] -settings.use_grpc_api = config["use_grpc"] -if settings.use_local_example_data: - settings.local_example_folder = config["local_example_folder"] -close_desktop = config["close_desktop"] - -logger = pyaedt_logger - - -def generate_random_string(length): - characters = string.ascii_letters + string.digits - random_string = "".join(random.sample(characters, length)) - return random_string - - -def generate_random_ident(): - ident = "-" + generate_random_string(6) + "-" + generate_random_string(6) + "-" + generate_random_string(6) - return ident - - -def _delete_objects(): - settings.remote_api = False - pyaedt_logger.remove_all_project_file_logger() - try: - del sys.modules["glob"] - except Exception: - logger.debug("Failed to delete glob module") - gc.collect() - - -@pytest.fixture(scope="session", autouse=True) -def init_scratch(): - test_folder_name = "unit_test" + generate_random_ident() - test_folder = os.path.join(tempfile.gettempdir(), test_folder_name) - try: - os.makedirs(test_folder, mode=0o777) - except FileExistsError as e: - print(f"Failed to create {test_folder}. Reason: {e}") - - yield test_folder - - try: - shutil.rmtree(test_folder, ignore_errors=True) - except Exception as e: - print(f"Failed to delete {test_folder}. Reason: {e}") - - -@pytest.fixture(scope="module", autouse=True) -def local_scratch(init_scratch): - tmp_path = init_scratch - scratch = Scratch(tmp_path) - yield scratch - scratch.remove() - - -@pytest.fixture(scope="module", autouse=True) -def desktop(): - _delete_objects() - keys = list(_desktop_sessions.keys()) - for key in keys: - del _desktop_sessions[key] - d = Desktop(desktop_version, NONGRAPHICAL, new_thread) - d.odesktop.SetTempDirectory(tempfile.gettempdir()) - d.disable_autosave() - if desktop_version > "2022.2": - d.odesktop.SetDesktopConfiguration("All") - d.odesktop.SetSchematicEnvironment(0) - yield d - pid = d.aedt_process_id - d.close_desktop() - time.sleep(1) - try: - os.kill(pid, 9) - except OSError: - pass - - -@pytest.fixture(scope="module") -def add_app(local_scratch): - def _method( - project_name=None, design_name=None, solution_type=None, application=None, subfolder="", just_open=False - ): - if project_name and not just_open: - example_project = os.path.join( - TESTS_VISUALIZATION_PATH, "example_models", subfolder, project_name + ".aedt" - ) - example_folder = os.path.join(TESTS_VISUALIZATION_PATH, "example_models", subfolder, project_name + ".aedb") - if os.path.exists(example_project): - test_project = local_scratch.copyfile(example_project) - elif os.path.exists(example_project + "z"): - example_project = example_project + "z" - test_project = local_scratch.copyfile(example_project) - else: - test_project = os.path.join(local_scratch.path, project_name + ".aedt") - if os.path.exists(example_folder): - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") - local_scratch.copyfolder(example_folder, target_folder) - elif project_name and just_open: - test_project = project_name - else: - test_project = None - if not application: - application = Hfss - - args = { - "project": test_project, - "design": design_name, - "version": desktop_version, - "non_graphical": NONGRAPHICAL, - "remove_lock": True, - } - if solution_type: - args["solution_type"] = solution_type - return application(**args) - - return _method - - -@pytest.fixture(scope="module") -def test_project_file(local_scratch): - def _method(project_name=None, subfolder=None): - if subfolder: - project_file = os.path.join(TESTS_VISUALIZATION_PATH, "example_models", subfolder, project_name + ".aedt") - else: - project_file = os.path.join(local_scratch.path, project_name + ".aedt") - if os.path.exists(project_file): - return project_file - else: - return None - - return _method - - -@pytest.fixture(scope="module") -def add_edb(local_scratch): - def _method(project_name=None, subfolder=""): - if project_name: - example_folder = os.path.join(TESTS_VISUALIZATION_PATH, "example_models", subfolder, project_name + ".aedb") - if os.path.exists(example_folder): - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") - local_scratch.copyfolder(example_folder, target_folder) - else: - target_folder = os.path.join(local_scratch.path, project_name + ".aedb") - else: - target_folder = os.path.join(local_scratch.path, generate_unique_name("TestEdb") + ".aedb") - return Edb( - target_folder, - edbversion=desktop_version, - ) - - return _method - - -@pytest.fixture(scope="function") -def lumped_design(): - """Fixture for creating a LumpedDesign object.""" - return LumpedDesign(config["desktopVersion"]) - - -@pytest.fixture(scope="function") -def distributed_design(): - """Fixture for creating a DistributedDesign object.""" - return DistributedDesign(config["desktopVersion"]) diff --git a/tests/system/visualization/test_12_1_PostProcessing.py b/tests/system/visualization/test_12_1_PostProcessing.py index 044c3b93e10..62f57dc5ac8 100644 --- a/tests/system/visualization/test_12_1_PostProcessing.py +++ b/tests/system/visualization/test_12_1_PostProcessing.py @@ -37,7 +37,7 @@ from ansys.aedt.core.visualization.plot.pyvista import ModelPlotter from ansys.aedt.core.visualization.plot.pyvista import _parse_aedtplt from tests import TESTS_VISUALIZATION_PATH -from tests.system.visualization.conftest import config +from tests.conftest import config test_project_name = "coax_setup_solved_231" m2d_trace_export_table = "m2d" diff --git a/tests/system/visualization/test_12_PostProcessing.py b/tests/system/visualization/test_12_PostProcessing.py index 509d6ace505..14672865bdd 100644 --- a/tests/system/visualization/test_12_PostProcessing.py +++ b/tests/system/visualization/test_12_PostProcessing.py @@ -39,7 +39,7 @@ from ansys.aedt.core.visualization.plot.pyvista import _parse_aedtplt from ansys.aedt.core.visualization.plot.pyvista import _parse_streamline from tests import TESTS_VISUALIZATION_PATH -from tests.system.visualization.conftest import config +from tests.conftest import config test_field_name = "Potter_Horn_242" q3d_file = "via_gsg_solved" diff --git a/tests/system/visualization/test_PostProcessing_Field_Report.py b/tests/system/visualization/test_PostProcessing_Field_Report.py index 58048fb6b70..b75dc4215f7 100644 --- a/tests/system/visualization/test_PostProcessing_Field_Report.py +++ b/tests/system/visualization/test_PostProcessing_Field_Report.py @@ -169,7 +169,7 @@ def test_reports_by_category_far_antenna_parameters_2(self, h3d_potter_horn): def test_create_report_from_configuration_template(self, h3d_potter_horn): from tests import TESTS_VISUALIZATION_PATH - from tests.system.visualization.conftest import config + from tests.conftest import config new_report4 = h3d_potter_horn.post.reports_by_category.antenna_parameters( "db(PeakRealizedGain)", infinite_sphere="3D" diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py deleted file mode 100644 index edae4f43d13..00000000000 --- a/tests/unit/conftest.py +++ /dev/null @@ -1,27 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2021 - 2025 ANSYS, Inc. and/or its affiliates. -# SPDX-License-Identifier: MIT -# -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from ansys.aedt.core.generic.settings import settings - -settings.enable_error_handler = False diff --git a/tests/unit/extensions/conftest.py b/tests/unit/extensions/conftest.py index 73b759c7ea8..5ca9aa65a81 100644 --- a/tests/unit/extensions/conftest.py +++ b/tests/unit/extensions/conftest.py @@ -22,6 +22,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +""" +Unit Extensions Test Configuration +---------------------------------- + +This conftest.py contains configurations specific to unit extension tests. +It provides mock fixtures for testing extensions without requiring full +AEDT applications. General configurations are inherited from top-level. +""" + from unittest.mock import MagicMock from unittest.mock import PropertyMock from unittest.mock import patch @@ -34,64 +43,59 @@ @pytest.fixture def mock_icepak_app(): """Fixture to mock Icepak application.""" - with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_aedt_application_property: - mock_aedt_application_instance = MagicMock() - mock_aedt_application_instance.design_type = "Icepak" - mock_aedt_application_property.return_value = mock_aedt_application_instance - - yield mock_aedt_application_instance + with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_property: + mock_instance = MagicMock() + mock_instance.design_type = "Icepak" + mock_property.return_value = mock_instance + yield mock_instance @pytest.fixture def mock_hfss_app(): """Fixture to mock HFSS application.""" - with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_aedt_application_property: - mock_aedt_application_instance = MagicMock() - mock_aedt_application_instance.design_type = "HFSS" - mock_aedt_application_property.return_value = mock_aedt_application_instance - - yield mock_aedt_application_instance + with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_property: + mock_instance = MagicMock() + mock_instance.design_type = "HFSS" + mock_property.return_value = mock_instance + yield mock_instance @pytest.fixture def mock_hfss_3d_layout_app(): - """Fixture to mock HFSS application.""" - with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_aedt_application_property: - mock_aedt_application_instance = MagicMock() - mock_aedt_application_instance.design_type = "HFSS 3D Layout Design" - mock_aedt_application_property.return_value = mock_aedt_application_instance - - yield mock_aedt_application_instance + """Fixture to mock HFSS 3D Layout application.""" + with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_property: + mock_instance = MagicMock() + mock_instance.design_type = "HFSS 3D Layout Design" + mock_property.return_value = mock_instance + yield mock_instance @pytest.fixture def mock_maxwell_3d_app(): """Fixture to mock Maxwell 3D application.""" - with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_aedt_application_property: - mock_aedt_application_instance = MagicMock() - mock_aedt_application_instance.design_type = "Maxwell 3D" - mock_aedt_application_property.return_value = mock_aedt_application_instance - - yield mock_aedt_application_instance + with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_property: + mock_instance = MagicMock() + mock_instance.design_type = "Maxwell 3D" + mock_property.return_value = mock_instance + yield mock_instance @pytest.fixture def mock_maxwell_2d_app(): - """Fixture to mock Maxwell 3D application.""" - with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_aedt_application_property: - mock_aedt_application_instance = MagicMock() - mock_aedt_application_instance.design_type = "Maxwell 2D" - mock_aedt_application_property.return_value = mock_aedt_application_instance - - yield mock_aedt_application_instance + """Fixture to mock Maxwell 2D application.""" + with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_property: + mock_instance = MagicMock() + mock_instance.design_type = "Maxwell 2D" + mock_property.return_value = mock_instance + yield mock_instance @pytest.fixture def mock_circuit_app(): """Fixture to mock Circuit application.""" - with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_aedt_application_property: - mock_aedt_application_instance = MagicMock() - mock_aedt_application_instance.design_type = "Circuit Design" - mock_aedt_application_property.return_value = mock_aedt_application_instance + with patch.object(ExtensionCommon, "aedt_application", new_callable=PropertyMock) as mock_property: + mock_instance = MagicMock() + mock_instance.design_type = "Circuit Design" + mock_property.return_value = mock_instance - yield mock_aedt_application_instance + yield mock_instance