From 9a36d37edd8db01bc719c10fe0bb2e845e2f607a Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Tue, 24 Jun 2025 10:06:52 +0100 Subject: [PATCH 01/38] update dependency groups --- .github/dependabot.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b5d1656a..d5302a07 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,6 +7,11 @@ updates: labels: - "maintenance" - "dependencies" + groups: + production-dependencies: + dependency-type: "production" + development-dependencies: + dependency-type: "development" - package-ecosystem: "github-actions" directory: "/" From ee24ad6cac7d30b4abf658690b6d0e68bed81ec9 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Tue, 24 Jun 2025 09:10:42 +0000 Subject: [PATCH 02/38] chore: adding changelog file 245.miscellaneous.md [dependabot-skip] --- doc/changelog.d/245.miscellaneous.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/245.miscellaneous.md diff --git a/doc/changelog.d/245.miscellaneous.md b/doc/changelog.d/245.miscellaneous.md new file mode 100644 index 00000000..7373fb94 --- /dev/null +++ b/doc/changelog.d/245.miscellaneous.md @@ -0,0 +1 @@ +Group dependencies together \ No newline at end of file From bf34fa83327da6d5962682852b507b6714384c68 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Tue, 24 Jun 2025 13:54:34 +0100 Subject: [PATCH 03/38] start but stuck with getting optislang files --- tests/e2e/test_optislang_e2e.py | 21 ++++++++++ .../integration/test_optislang_integration.py | 41 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/e2e/test_optislang_e2e.py create mode 100644 tests/integration/test_optislang_integration.py diff --git a/tests/e2e/test_optislang_e2e.py b/tests/e2e/test_optislang_e2e.py new file mode 100644 index 00000000..919240ea --- /dev/null +++ b/tests/e2e/test_optislang_e2e.py @@ -0,0 +1,21 @@ +# Copyright (C) 2023 - 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. diff --git a/tests/integration/test_optislang_integration.py b/tests/integration/test_optislang_integration.py new file mode 100644 index 00000000..cd681424 --- /dev/null +++ b/tests/integration/test_optislang_integration.py @@ -0,0 +1,41 @@ +# Copyright (C) 2023 - 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. + +# Get optislang version and integration (wrong way round) so special python +# version and inject my code into it. +# Or inject optislang into my code. For the e2e it has to be the first one. +# Therefore lets do the same here. + +# USE OPTISLANG PYTHON +import sys + +sys.path.append("C:\\Program Files\\ANSYS Inc\\v251\\optiSLang\\lib\\python-modules") +sys.path.append("C:\\Program Files\\ANSYS Inc\\v251\\optiSLang\\scripting\\integrations") + +print(sys.path) +import conceptev_ci as conceptev_ci + + +def test_pass(): + """Test that the optislang integration works.""" + print(dir(conceptev_ci)) + assert True From f4941311396fa35869c19e38ad57724097d169ca Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Wed, 25 Jun 2025 09:04:04 +0100 Subject: [PATCH 04/38] started integration tests --- tests/integration/config.toml | 9 +++ .../integration/test_optislang_integration.py | 72 +++++++++++++++---- 2 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 tests/integration/config.toml diff --git a/tests/integration/config.toml b/tests/integration/config.toml new file mode 100644 index 00000000..bf043ca6 --- /dev/null +++ b/tests/integration/config.toml @@ -0,0 +1,9 @@ +OCM_URL = "https://dev.portal.onscale.com/api" +OCM_SOCKET_URL = "wss://sockets.dev.portal.onscale.com/socket" +CONCEPTEV_URL = "https://test-conceptev.awsansys3np.onscale.com/api" +client_id = "9c9edb71-06f9-4c4b-afed-9201668385de" +authority = "https://a365dev.b2clogin.com/a365dev.onmicrosoft.com/b2c_1a_ansysid_signup_signin_test" +scope = "https://a365dev.onmicrosoft.com/AnsysID/Authentication" +conceptev_username = "conceptev_testing@ansys.com" +account_name = "ConceptEv Test Account" +job_timeout = 3600 \ No newline at end of file diff --git a/tests/integration/test_optislang_integration.py b/tests/integration/test_optislang_integration.py index cd681424..58b4189b 100644 --- a/tests/integration/test_optislang_integration.py +++ b/tests/integration/test_optislang_integration.py @@ -20,22 +20,68 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# Get optislang version and integration (wrong way round) so special python -# version and inject my code into it. -# Or inject optislang into my code. For the e2e it has to be the first one. -# Therefore lets do the same here. +# Optislang Integration Test +# A poor mans integration test for the optislang integration. +# Looks at conceptev/utils/api_helper.py to see pyconceptev usage within ConceptEV integration. -# USE OPTISLANG PYTHON -import sys +from ansys.conceptev.core import auth, exceptions -sys.path.append("C:\\Program Files\\ANSYS Inc\\v251\\optiSLang\\lib\\python-modules") -sys.path.append("C:\\Program Files\\ANSYS Inc\\v251\\optiSLang\\scripting\\integrations") -print(sys.path) -import conceptev_ci as conceptev_ci +def test_exceptions(): + """Example Exception Usage in api_helper""" + try: + raise exceptions.ResponseError("This is a test error") + except exceptions.ResponseError as e: + assert e.args[0].lower() -def test_pass(): +def test_auth_app(): """Test that the optislang integration works.""" - print(dir(conceptev_ci)) - assert True + msal_app = auth.create_msal_app() + token = auth.get_ansyId_token(msal_app) + + +# def test_app(): +# app.get_http_client(token, design_instance_id) +# client = app.get_http_client(token) +# concept = app.get(client, "/concepts", id=design_instance_id, params={"populated": False}) +# concept["configurations"] = app.get(client, f"/concepts/{design_instance_id}/configurations") +# concept["components"] = app.get(client, f"/concepts/{design_instance_id}/components") +# concept["requirements"] = app.get(client, f"/concepts/{design_instance_id}/requirements") +# arch_id = concept['architecture_id'] +# concept["architecture"] = app.get( +# client, +# f"/architectures/{arch_id}", +# params={"design_instance_id": design_instance_id} +# ) +# concept_data = app.get_concept(client, design_instance_id) +# data_types ????? +# posted_data = app.post(client, f"/{data_type}", data=data) +# accounts = app.get_account_ids(token) +# hpc_id = app.get_default_hpc(token, account_id) +# job_info = app.create_submit_job( +# client, +# concept_data, +# account_id, +# hpc_id, +# job_name +# ) +# job_results = app.read_results( +# client, +# job_info, +# calculate_units=calculate_units, +# filtered=filtered_results, +# ) +# app.post(client, "/jobs:error_file", data=data) +# health = app.get(client, "/health") +# app.create_new_project( +# client, account_id, hpc_id, f"{project_name}" +# ) +# concept_data = app.create_new_concept( +# client, +# project_id, +# title=title, +# ) +# accounts = app.get_account_ids(token) +# app.get_project_ids(re.escape(project_name), account_id, token) +# created_component = app.post_component_file(client, str(filepath), component_type) From abc3f06ade92b363cf280f53e163c34ab9cbe291 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Mon, 30 Jun 2025 17:07:47 +0100 Subject: [PATCH 05/38] main endpoints tested just need post to components --- poetry.lock | 4 +- .../integration/test_optislang_integration.py | 315 +++++++++++++++--- 2 files changed, 272 insertions(+), 47 deletions(-) diff --git a/poetry.lock b/poetry.lock index d9b04fd5..0ebedd26 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.2 and should not be changed by hand. [[package]] name = "accessible-pygments" @@ -1342,7 +1342,7 @@ description = "Read resources from Python packages" optional = false python-versions = ">=3.9" groups = ["doc"] -markers = "python_version < \"3.10\"" +markers = "python_version == \"3.9\"" files = [ {file = "importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec"}, {file = "importlib_resources-6.5.2.tar.gz", hash = "sha256:185f87adef5bcc288449d98fb4fba07cea78bc036455dd44c5fc4a2fe78fed2c"}, diff --git a/tests/integration/test_optislang_integration.py b/tests/integration/test_optislang_integration.py index 58b4189b..4af35f09 100644 --- a/tests/integration/test_optislang_integration.py +++ b/tests/integration/test_optislang_integration.py @@ -20,11 +20,151 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +import re + +import httpx +import jwt + # Optislang Integration Test # A poor mans integration test for the optislang integration. # Looks at conceptev/utils/api_helper.py to see pyconceptev usage within ConceptEV integration. +import pytest + +from ansys.conceptev.core import app, auth, exceptions + + +@pytest.fixture +def msal_app(): + """Fixture to create a MSAL PublicClientApplication instance.""" + return auth.create_msal_app() + + +@pytest.fixture +def token(msal_app): + """Fixture to get a valid AnsysID token.""" + token = auth.get_ansyId_token(msal_app) + return token + + +@pytest.fixture +def client(token): + """Fixture to provide a client for testing.""" + with app.get_http_client(token) as client: + yield client + + +@pytest.fixture +def design_instance_id(): + """Fixture to provide a design instance ID for testing.""" + return "8cdea42d-fb8a-4499-a6f9-a188f2454afa" + + +@pytest.fixture +def client_with_design_instance(design_instance_id, token): + """Fixture to provide a client with a design instance ID for testing.""" + with app.get_http_client(token, design_instance_id) as client: + yield client + + +@pytest.fixture +def accounts(token): + """Fixture to get accounts.""" + accounts = app.get_account_ids(token) + return accounts + + +@pytest.fixture +def concept_data(client_with_design_instance, design_instance_id): + """Fixture to get concept data.""" + concept_data = app.get_concept(client_with_design_instance, design_instance_id) + return concept_data + + +@pytest.fixture +def account_id(accounts): + """Fixture to provide an account ID for testing.""" + return accounts[auth.settings.account_name] + + +@pytest.fixture +def hpc_id(token, account_id): + """Fixture to get the HPC ID.""" + hpc_id = app.get_default_hpc(token, account_id) + return hpc_id + + +@pytest.fixture +def job_info(client_with_design_instance, concept_data, account_id, hpc_id): + """Submit a job to the HPC.""" + job_info = app.create_submit_job( + client_with_design_instance, + concept_data, + account_id, + hpc_id, + ) + return job_info + + +@pytest.fixture +def read_results(client_with_design_instance, job_info): + """Read results from the job.""" + read_results = app.read_results( + client_with_design_instance, + job_info, + calculate_units=False, + filtered=True, + ) + return read_results + + +@pytest.fixture +def console_log(job_info, client_with_design_instance): + console_log = app.post(client_with_design_instance, "/jobs:error_file", data=job_info) + return console_log + + +@pytest.fixture +def project_name(): + """Project name fixture.""" + return "Integration Test from pyconceptev" + + +@pytest.fixture +def created_project(client, account_id, hpc_id, token, project_name): + + created_project = app.create_new_project(client, account_id, hpc_id, f"{project_name}") + yield created_project + app.delete_project(created_project["projectId"], token) + + +@pytest.fixture +def project_id(created_project): + """Fixture to provide a project ID for testing.""" + return created_project["projectId"] + + +@pytest.fixture +def created_concept(client, project_id): + concept_data = app.create_new_concept( + client, + project_id, + title="ConceptEV Integration Test", + ) + return concept_data -from ansys.conceptev.core import auth, exceptions + +@pytest.fixture +def account_ids(token): + """Fixture to get accounts.""" + account_ids = app.get_account_ids(token) + return account_ids + + +@pytest.fixture +def project_ids(project_name, created_project, account_id, token): + """Fixture to get project IDs.""" + project_ids = app.get_project_ids(re.escape(project_name), account_id, token) + return project_ids def test_exceptions(): @@ -35,53 +175,138 @@ def test_exceptions(): assert e.args[0].lower() -def test_auth_app(): +def test_msal_app(msal_app): + """Test that the MSAL PublicClientApplication is created.""" + assert isinstance(msal_app, auth.PublicClientApplication) + assert msal_app.client_id == auth.client_id + assert msal_app.authority.authorization_endpoint == auth.authority + "/oauth2/v2.0/authorize" + + +def test_auth_app(token): """Test that the optislang integration works.""" - msal_app = auth.create_msal_app() - token = auth.get_ansyId_token(msal_app) + assert isinstance(token, str) + claims = jwt.decode(token, options={"verify_signature": False}) + # Step 1: Fetch JWKS + jwks = httpx.get(auth.settings.authority + "/discovery/v2.0/keys").json() + + # Step 2: Get headers from token to find correct kid + unverified_header = jwt.get_unverified_header(token) + kid = unverified_header["kid"] + key = next(k for k in jwks["keys"] if k["kid"] == kid) + public_key = jwt.algorithms.RSAAlgorithm.from_jwk(key) + algorithm = unverified_header["alg"] + jwt.decode(token, public_key, verify=True, algorithms=algorithm, options={"verify_aud": False}) + + +def test_client(client, token): + """Test that the client can make a request.""" + assert str(client.base_url).strip("/") == auth.settings.conceptev_url + assert client.headers["Authorization"] == f"{token}" + + +def test_client_design_instance(client_with_design_instance, token, design_instance_id): + """Test that the client can make a request with a design instance.""" + assert str(client_with_design_instance.base_url).strip("/") == auth.settings.conceptev_url + assert client_with_design_instance.headers["Authorization"] == f"{token}" + assert client_with_design_instance.params["design_instance_id"] == design_instance_id + # Additional checks can be added here for specific endpoints or data + + +def test_health(client): + """Test the health endpoint.""" + response = client.get("/health") + assert response.status_code == 200 + assert response.json()["name"] == "ConceptEV" + + +def test_authorised(client): + """Test the health endpoint.""" + response = client.get("/authenticated_user") + assert response.status_code == 200 + + +def test_get_concept(client, client_with_design_instance, design_instance_id, concept_data): + """Test getting a concept and getting ids.""" + concept = app.get(client, "/concepts", id=design_instance_id, params={"populated": False}) + concept["configurations"] = app.get( + client_with_design_instance, f"/concepts/{design_instance_id}/configurations" + ) + concept["components"] = app.get( + client_with_design_instance, f"/concepts/{design_instance_id}/components" + ) + concept["requirements"] = app.get( + client_with_design_instance, f"/concepts/{design_instance_id}/requirements" + ) + arch_id = concept["architecture_id"] + concept["architecture"] = app.get( + client_with_design_instance, + f"/architectures/{arch_id}", + params={"design_instance_id": design_instance_id}, + ) + assert concept == concept_data + + +def test_accounts(accounts, token): + """Test accounts endpoint.""" + assert isinstance(accounts, dict) + assert auth.settings.account_name in accounts + + +def test_hpc_endpoint(hpc_id): + + assert isinstance(hpc_id, str) + assert len(hpc_id) > 0, "HPC ID should not be empty" + + +def test_submit_job(job_info): + assert isinstance(job_info, dict) + assert "job_id" in job_info + return job_info + + +def test_read_results(read_results): + """Test reading results from the job.""" + assert isinstance(read_results, list) + assert read_results[0]["feasible"] == True + assert len(read_results) > 0, "Results should not be empty" + + +def test_console_log(read_results, console_log): + """Test reading the console log.""" + assert isinstance(console_log, str) + assert len(console_log) > 0, "Console log should not be empty" + + +def test_create_project(created_project): + """Test creating a project.""" + assert isinstance(created_project, dict) + assert "projectId" in created_project + assert created_project["projectTitle"] == "Integration Test from pyconceptev" + + +def test_created_concept(created_concept, project_id): + """Test creating a concept.""" + assert isinstance(created_concept, dict) + assert created_concept["project_id"] == project_id + assert "design_instance_id" in created_concept + + +def test_get_accounts(account_ids, account_id): + """Test getting accounts.""" + assert isinstance(account_ids, dict) + assert auth.settings.account_name in account_ids + assert account_id in account_ids.values() + + +def test_project_ids(project_ids, project_id, project_name): + """Test project ids""" + assert isinstance(project_ids, dict) + assert project_name in project_ids + assert isinstance(project_ids[project_name], list) + assert project_id in project_ids[project_name] -# def test_app(): -# app.get_http_client(token, design_instance_id) -# client = app.get_http_client(token) -# concept = app.get(client, "/concepts", id=design_instance_id, params={"populated": False}) -# concept["configurations"] = app.get(client, f"/concepts/{design_instance_id}/configurations") -# concept["components"] = app.get(client, f"/concepts/{design_instance_id}/components") -# concept["requirements"] = app.get(client, f"/concepts/{design_instance_id}/requirements") -# arch_id = concept['architecture_id'] -# concept["architecture"] = app.get( -# client, -# f"/architectures/{arch_id}", -# params={"design_instance_id": design_instance_id} -# ) -# concept_data = app.get_concept(client, design_instance_id) # data_types ????? # posted_data = app.post(client, f"/{data_type}", data=data) -# accounts = app.get_account_ids(token) -# hpc_id = app.get_default_hpc(token, account_id) -# job_info = app.create_submit_job( -# client, -# concept_data, -# account_id, -# hpc_id, -# job_name -# ) -# job_results = app.read_results( -# client, -# job_info, -# calculate_units=calculate_units, -# filtered=filtered_results, -# ) -# app.post(client, "/jobs:error_file", data=data) -# health = app.get(client, "/health") -# app.create_new_project( -# client, account_id, hpc_id, f"{project_name}" -# ) -# concept_data = app.create_new_concept( -# client, -# project_id, -# title=title, -# ) -# accounts = app.get_account_ids(token) -# app.get_project_ids(re.escape(project_name), account_id, token) + # created_component = app.post_component_file(client, str(filepath), component_type) From c5f5a5cfcc569d74785b6f807d8f2289f2c9bf3e Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Tue, 8 Jul 2025 15:15:05 +0100 Subject: [PATCH 06/38] current wip for testing with pyoptislang --- tests/e2e/test_optislang_e2e.py | 194 ++++++++++++++++++ tests/integration/e9.lab | 1 + .../integration/test_optislang_integration.py | 126 +++++++++++- 3 files changed, 316 insertions(+), 5 deletions(-) create mode 100644 tests/integration/e9.lab diff --git a/tests/e2e/test_optislang_e2e.py b/tests/e2e/test_optislang_e2e.py index 919240ea..137a8e68 100644 --- a/tests/e2e/test_optislang_e2e.py +++ b/tests/e2e/test_optislang_e2e.py @@ -19,3 +19,197 @@ # 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 logging +import os +import shutil + +# from ansys.optislang.core import Optislang +# from ansys.optislang.core import examples +# from ansys.optislang.core import Optislang +# from ansys.optislang.core.nodes import DesignFlow +# import ansys.optislang.core.node_types as node_types +from ansys.optislang.core import Optislang +import ansys.optislang.core.node_types as node_types +from ansys.optislang.core.nodes import DesignFlow +from ansys.optislang.core.project_parametric import ( + ComparisonType, + ConstraintCriterion, + ObjectiveCriterion, +) + + +class QueryHandler(logging.Handler): + def __init__(self, log_filepath=None): + super().__init__() + self._collected_messages = [] + self.log_filepath = log_filepath + + def emit(self, record): + self._collected_messages.append(record.getMessage()) + if self.log_filepath is not None: + with open(str(self.log_filepath), "a") as f: + f.write(record.getMessage() + "\n") + + def get_messages(self): + collected_messages = [msg for msg in self._collected_messages] + self._collected_messages = [] + return collected_messages + + +class LogFilter(logging.Filter): + def __init__(self, level): + super().__init__() + self._level = level + + def filter(self, record): + return record.levelno <= self._level + + +def prepare_logging_facilities(osl_object, working_dir): + osl_object.log.setLevel(logging.DEBUG) + error_handler = QueryHandler(os.path.join(working_dir, "stderr.txt")) + error_handler.setLevel(logging.WARNING) + std_handler = QueryHandler(os.path.join(working_dir, "stdout.txt")) + std_handler.setLevel(logging.DEBUG) + std_handler.addFilter(LogFilter(logging.INFO)) + + osl_object.log.addHandler(std_handler) + osl_object.log.addHandler(error_handler) + + return std_handler, error_handler + + +def register_parameter(node, name): + location = get_input_location_by_name(node, name) + node.register_location_as_parameter( + location=location, + name=name, + ) + + +def get_input_location_by_name(node, name): + input_locations = node.get_available_input_locations() + for loc in input_locations: + if loc["location"]["name"] == name: + return loc["location"] + raise KeyError(f"Input location '{name}' not found.") + + +def get_output_location_by_name(node, name): + output_locations = node.get_available_output_locations() + for loc in output_locations: + if loc["location"]["name"] == name: + return loc["location"] + raise KeyError(f"Output location '{name}' not found.") + + +def register_response(node, name): + location = get_output_location_by_name(node, name) + node.register_location_as_response( + location=location, + name=name, + ) + + +def get_unit_test_dir(): + unit_test_dir = os.path.join(".") + return unit_test_dir + + +def get_working_dir(): + return os.path.join(get_unit_test_dir(), "test_working_dir") + + +def remove_non_empty_dir(path): + if os.path.exists(path): + shutil.rmtree(path, ignore_errors=False, onerror=None) + + +def test_optislang_connection() -> None: + # create fresh working directory + # this is logging in interactively and connecting to prod server at the moment + working_dir = get_working_dir() + opf_filepath = os.path.join(working_dir, "test_conceptev_ci.opf") + opd_dir = os.path.join(working_dir, "test_conceptev_ci.opd") + remove_non_empty_dir(working_dir) + os.makedirs(working_dir) + + osl_project_path = os.path.join(working_dir, "test_conceptev_ci.opf") + + # created concept + # configure environment + design_instance_id = "7a906ce3-76ad-49ce-b707-ac38e4efdcbd" # Need a completed job? + osl = Optislang(loglevel="DEBUG", project_path=osl_project_path) + print(osl) + osl.osl_server.timeouts_register.default_value = 180 + std_handler, err_handler = prepare_logging_facilities(osl, working_dir) + + root_system = osl.application.project.root_system + sensitivity = root_system.create_node(type_=node_types.Sensitivity) + concept_ev_node_type = node_types.NodeType( + id="conceptev", + subtype=node_types.AddinType.PYTHON_BASED_INTEGRATION_PLUGIN, + osl_class_type=node_types.NodeClassType.INTEGRATION_NODE, + ) + node_name = "conceptev" + cev_node = sensitivity.create_node( + type_=concept_ev_node_type, + name=node_name, + design_flow=DesignFlow.RECEIVE_SEND, + ) + non_modifying_settings = cev_node.get_property("NonModifyingSettings") + non_modifying_settings["cev_account_name"] = "conceptev_saas@ansys.com" + cev_node.set_property("NonModifyingSettings", non_modifying_settings) + modifying_settings = cev_node.get_property("ModifyingSettings") + modifying_settings["cev_concept_id"] = design_instance_id + cev_node.set_property("ModifyingSettings", modifying_settings) + cev_node.load() + + input_locations = cev_node.get_available_input_locations() + output_locations = cev_node.get_available_output_locations() + register_parameter(cev_node, "rear_motor") + + register_response(cev_node, "_00__capability_curve__torque_vs_speed") + register_response(cev_node, "_01__summary__cost") + register_response(cev_node, "_01__summary__mass") + register_response(cev_node, "_01__summary__constraints_fulfilled") + register_response(cev_node, "_01__summary__n_constraints_fulfilled") + + sensitivity.criteria_manager.add_criterion( + ObjectiveCriterion( + name="obj_cost", expression="_01__summary__cost", criterion=ComparisonType.MIN + ) + ) + sensitivity.criteria_manager.add_criterion( + ConstraintCriterion( + name="constraints_fulfilled", + expression="_01__summary__n_constraints_fulfilled", + criterion=ComparisonType.GREATEREQUAL, + limit_expression="1", + ) + ) + + # limit the number of designs to compute + algo_settings = sensitivity.get_property("AlgorithmSettings") + algo_settings["num_discretization"] = 10 + sensitivity.set_property("AlgorithmSettings", algo_settings) + + # define parallelism + cev_node.set_property("MaxParallel", 10) + + # define max runtime + cev_node.set_property("MaxRuntime", 180000) # milliseconds + + # save + osl.application.save() + + # run + osl.application.project.start() + + # save and close + osl.application.save() + osl.dispose() + + stderr = "".join(err_handler.get_messages()) + stdout = "".join(std_handler.get_messages()) diff --git a/tests/integration/e9.lab b/tests/integration/e9.lab new file mode 100644 index 00000000..f9fb25b2 --- /dev/null +++ b/tests/integration/e9.lab @@ -0,0 +1 @@ +{"LabModelExportFilePath": "C:\\Workspace\\ConceptEV\\ConceptEV\\ConceptEV-API\\data\\Lab_Data\\e9.lab", "TimeoutMultiplier_Lab": 1, "MessageDisplayState": 0, "MotorType_MotorLAB": "BPM", "CurrentMotFilePath_MotorLAB": "C:\\Ansys_Motor-CAD\\2024_0_4\\Motor-CAD Data\\templates\\e9_eMobility_IPM.mtt", "ResultsPath_MotorLAB": "C:\\Ansys_Motor-CAD\\2024_0_4\\Motor-CAD Data\\templates\\e9_eMobility_IPM\\Lab\\", "ComparisonPath_Lab": "", "UserLoadedResultsFile_Lab": "", "ElectroLink_MotorLAB": "Motor-CAD EMag", "DrivCycle_MotorLAB": 3, "Duty_Cycle_Definition": 3, "Duty_Cycle_SyncCurrentLimit_Method_Lab": 1, "DutyCycleType_Lab": 1, "ExpData_MotorLAB": "False", "ExpDataType_MotorLAB": 0, "ExpDataPath_MotorLAB": "", "CurrentExeDir_MotorLAB": "C:\\Ansys_Motor-CAD\\2024_0_4\\", "AutoShowResults_MotorLAB": "True", "SaturationMap_InputDefinition": 0, "SaturationMap_CalculationMethod": 0, "SaturationMap_FEACalculationType": 1, "SaturationMap_ResultType": 0, "SaturationMap_FieldCurrentDefinition": 0, "SaturationMap_Export": true, "LossMap_Export": true, "SaturationMap_ExportToCSV": false, "SaturationMap_StatorCurrentMax": 150.0, "SaturationMap_StatorCurrentStep": 30.0, "SaturationMap_StatorCurrentMin": 0.0, "SaturationMap_PhaseAdvanceMax": 90.0, "SaturationMap_PhaseAdvanceStep": 22.5, "SaturationMap_PhaseAdvanceMin": 0.0, "SaturationMap_Current_D_Max": 0.0, "SaturationMap_Current_D_Step": 30.0, "SaturationMap_Current_D_Min": -150.0, "SaturationMap_Current_Q_Max": 150.0, "SaturationMap_Current_Q_Step": 30.0, "SaturationMap_Current_Q_Min": 0.0, "SaturationMap_FieldCurrentMax": 12.0, "SaturationMap_FieldCurrentStep": 4.0, "SaturationMap_FieldCurrentMin": 0.0, "ModelBuildSpeed_MotorLAB": 10000.0, "ModelBuildSpeed_Min_Lab": 50.0, "LossMap_Speed": 3000.0, "SpeedVariationType_Lab": 0, "SaturationMap_ExportFile": "", "SaturationModelInterpolation_Lab": 0, "MaxModelCurrent_MotorLAB": 480.0, "MaxModelCurrent_RMS_MotorLAB": 339.411254969543, "CalcTypeCuLoss_MotorLAB": 0, "SleeveLossCalc_Lab": 0, "BandingLossCalc_Lab": 0, "IronLossCalculationType": 0, "ProximityLossModel": 0, "HybridAdjustmentFactor_ACLosses": 1.0, "AcLossFreq_MotorLAB": 2.0, "n2ac_MotorLAB": 3000.0, "RacRdc_MotorLAB": 2.0, "StatorCopperFreqCompTempExponent": 0.5, "StatorConductor_Resistivity": 2.02361396e-08, "ACLosses_BundleHeight": 3.39411254969543, "NumberOfCuboids": 2, "NumberOfCuboids_LossModel_Lab": 2, "ACConductorLossProportion_Lab": [0.0, 0.0], "ACConductorLossSplit_Lab": 0, "ACLossSpeedScalingMethod_Lab": 1, "ACLossHighFrequencyScaling_Method": 1, "ACLossGeneratorMethod_Lab": 1, "TurnsRef_MotorLAB": 6.0, "TurnsCalc_MotorLAB": 6.0, "ResistanceTurnsRef_MotorLAB": 6.0, "Length_Calc_Lab": 160.0, "Length_Ref_Lab": 160.0, "Length_Ref_Resistance_Lab": 160.0, "LossModelBuildPoints_Lab": 30, "ACLossModelBuildPoints_Lab": 30, "LossModel_Is_Lab": [0.0, 0.0, 0.0, 0.0, 0.0, 96.0, 96.0, 96.0, 96.0, 96.0, 192.0, 192.0, 192.0, 192.0, 192.0, 288.0, 288.0, 288.0, 288.0, 288.0, 384.0, 384.0, 384.0, 384.0, 384.0, 480.0, 480.0, 480.0, 480.0, 480.0], "LossModel_Gamma_Lab": [0.0, 22.5, 45.0, 67.5, 90.0, 0.0, 22.5, 45.0, 67.5, 90.0, 0.0, 22.5, 45.0, 67.5, 90.0, 0.0, 22.5, 45.0, 67.5, 90.0, 0.0, 22.5, 45.0, 67.5, 90.0, 0.0, 22.5, 45.0, 67.5, 90.0], "FEALossMap_RefSpeed_Lab": 500.0, "IronLossBuildFactorDefinition": 0, "EddyLossBuildFactor": 1.0, "StatorIronLossBuildFactor": 1.5, "RotorIronLossBuildFactor": 1.5, "HysteresisLossBuildFactor": 1.0, "RotorLaminations": 0, "RotorIronEddyLossExponent_Lab": 2.0, "Pole_MotorLAB": 8.0, "TorqueDemand_MotorLAB": 200.0, "Housing_Water_Jacket": true, "Shaft_Spiral_Groove": false, "BPM_FilePath_MotorLAB": "", "EmagneticCalcType_Lab": 1, "MaxSpeedTherm_MotorLAB": 10000.0, "SpeedStepTherm_MotorLAB": 500.0, "MinSpeedTherm_Lab": 200.0, "MaxWindTemp_MotorLAB": 160.0, "ThermCalcType_MotorLAB": 0, "MaxWindingSpec_MotorLAB": 0, "TempLimit_MotorLAB": 1, "ThermalMapType_Lab": 0, "Iest_MotorLAB": 240.0, "Iest_RMS_MotorLAB": 169.705627484771, "ThermalConvergenceMethod_Lab": 1, "ThermalStatorWindingTemperatureMethod_Lab": 1, "Thermal_TemperaturesForEMag_Lab": 1, "ThermalEnvelopeSensitivity_Lab": 1.0, "RotorTemperatureTolerance_Lab": 1.0, "RotorTemperatureMaxIterations_Lab": 20, "RotorTemperatureIterationsBeforeAverage_Lab": 4, "RotorTemperatureIterationsInAverage_Lab": 3, "RotorTemperatureMaxDivergingSteps_Lab": 5, "RotorWindingTemp_Ref_Lab": 20.0, "RotorWindingTemp_Calc_Lab": 20.0, "Twdg_MotorLAB": 65.0, "Imax_MotorLAB": 480.0, "Imax_RMS_MotorLAB": 339.411254969543, "Imin_MotorLAB": 1.0, "Imin_RMS_MotorLAB": 0.707106781186547, "Iinc_MotorLAB": 30, "WindingTemp_ACLoss_Ref_Lab": 20.0, "PrevCalcImin_MotorLAB": 1.0, "PrevCalcIinc_MotorLAB": 30, "PrevCalcImax_MotorLAB": 480.0, "SpeedMax_MotorLAB": 10000.0, "SpeedMin_MotorLAB": 0.0, "SpeedInc_MotorLAB": 500.0, "IronLossModelSplit_Lab": 0, "IronLossModelSplit_Stator_Lab": 0, "IronLossModelSplit_Rotor_Lab": 0, "LossProp_Stator_Lab": 0.9, "LossProp_Rotor_Lab": 0.1, "LossProp_StatorBackIron_Lab": 0.45, "LossProp_StatorTooth_Lab": 0.55, "LossProp_RotorBackIron_Lab": 1.0, "LossProp_RotorPole_Lab": 0.0, "StatorCurrentDemand_Lab": 150.0, "StatorCurrentDemand_RMS_Lab": 106.066017177982, "SpeedDemand_MotorLAB": 1000.0, "PhaseAdvanceDemand_Lab": 0.0, "SlipDemand_Lab": 0.01, "StatorTempDemand_Lab": 160.0, "RotorTempDemand_Lab": 140.0, "OperatingMode_Lab": 2, "ThermMaxCurrentLim_MotorLAB": "False", "CurrentSpec_MotorLAB": 0, "TestType_MotorLAB": 0, "TestSpeedMin_MotorLAB": 10.0, "TestSpeedInc_MotorLAB": 10.0, "TestSpeedMax_MotorLAB": 1000.0, "Slots_MotorLAB": 48.0, "TwindingCalc_MotorLAB": 65.0, "Windage_Loss_Definition": 0, "BearingLossSource": 0, "Airgap_Temperature": 20.0, "Bearing_Temperature_F": 20.0, "Bearing_Temperature_R": 20.0, "Windage_Loss_@Ref_Speed": 0.0, "Ref_Speed_-_Windage_Loss": 3000.0, "Speed_Coeff_-_Windage_Loss": 3.0, "Friction_Loss_[F]_@Ref_Speed": 25.0, "Ref_Speed_-_Friction_Loss_[F]": 10000.0, "Speed_Coeff_-_Friction_Loss_[F]": 1.0, "Friction_Loss_[R]_@Ref_Speed": 25.0, "Ref_Speed_-_Friction_Loss_[R]": 10000.0, "Speed_Coeff_-_Friction_Loss_[R]": 1.0, "WindingAlpha_MotorLAB": 0.003862, "OpPointSpec_MotorLAB": 0, "MaxNumAltStartPoints_Lab": 2, "MinTorque_MotorLAB": 10.0, "TorqueInc_MotorLAB": 10.0, "TorqueMax_MotorLAB": 100.0, "LabThermalCoupling": 0, "LabMagneticCoupling": 0, "BuildSatModel_MotorLAB": "True", "BuildLossModel_MotorLAB": "True", "MaxRotorTemp_Lab": 160.0, "RotorCurrentEstimate_Lab": 6.0, "Resistance_MotorLAB": 0.0133773639742649, "EndWindingResistance_Lab": 0.00478887958376453, "EndWindingResistance_Field_Lab": 0.001, "EndWindingInductance_Lab": 5.2350555459915e-06, "ExternalLine_Resistance": 0.0, "Gen_Load_Definition_Lab": 0, "Gen_Load_Connection_Lab": 0, "Gen_Speed_Fixed_Lab": false, "Gen_Speed_Max_Lab": 6000.0, "Gen_Speed_Min_Lab": 0.0, "Gen_Speed_Step_Lab": 500.0, "Gen_Impedance_Fixed_Lab": false, "Gen_Impedance_Max_Lab": 10.0, "Gen_Impedance_Min_Lab": 1.0, "Gen_Impedance_Step_Lab": 1.0, "Gen_PF_Fixed_Lab": true, "Gen_PF_Max_Lab": 1.0, "Gen_PF_Min_Lab": 0.5, "Gen_PF_Step_Lab": 0.1, "Gen_Resistance_Fixed_Lab": false, "Gen_Resistance_Max_Lab": 10.0, "Gen_Resistance_Min_Lab": 1.0, "Gen_Resistance_Step_Lab": 1.0, "Gen_Inductance_Fixed_Lab": true, "Gen_Inductance_Max_Lab": 0.01, "Gen_Inductance_Min_Lab": 0.001, "Gen_Inductance_Step_Lab": 0.001, "Motor_Type": 0, "BPMDriveMode": 0, "DriveType_BPM": 0, "MagPhases": 3, "MagPhaseDistribution": 0, "WindingConnection": 0, "CustomDriveCyclePeakLineCurrent": 0.0, "CustomDriveFundamentalAmplitude": 0.0, "CustomDriveCyclePeakAmplitude": 0.0, "Lab_Threads_Enabled": true, "VoltageConversionFactor": 1.73205080756888, "FastRotorSkew_Lab": 1, "SkewType": 0, "StatorSkew": 0.0, "ContinuousSkewMethod": 1, "DCCurrentLimitExternaLine_Method_Lab": 1, "ElectricalCustomLoss_Method_Lab": 1, "NumCustomLossesInternal_Lab": 0, "CustomLoss_Name_Internal_Lab": [], "CustomLoss_Function_Internal_Lab": [], "CustomLoss_Type_Internal_Lab": [], "CustomLoss_ThermalNode_Internal_Lab": [], "NumCustomLossesExternal_Lab": 0, "CustomLoss_Name_External_Lab": [], "CustomLoss_PowerFunction_External_Lab": [], "CustomLoss_VoltageFunction_External_Lab": [], "CustomLoss_AllowedValues_Lab": 1, "NumCustomThermalLimits_Lab": 0, "CustomThermalLimitNode_Lab": [], "CustomThermalLimitTemperature_Lab": [], "CustomThermalLimit_Lab": [], "CustomThermalLimitName_Lab": [], "ModulationIndex_MotorLAB": 1.0, "DCBusVoltage": 400.0, "DCCurrentLimit_Lab": 0, "MaxDCCurrent_Lab": 80.0, "ModelType_MotorLAB": 2, "Ah_MotorLAB": 0.0, "Ae_MotorLAB": 0.0, "Bh_MotorLAB": 0.0, "Be_MotorLAB": 0.0, "Wmag_MotorLAB": 0.0, "WmagOC_MotorLAB": 0.0, "Imag_MotorLAB": 0.0, "Nmag_MotorLAB": 500.0, "NonSalient_MotorLAB": "False", "SatModelPoints_MotorLAB": 1, "SaturationModelMethod_Lab": 1, "ACLossModelBuildPoints_Current_Lab": 4, "ACLossModelBuildPoints_Gamma_Lab": 4, "ACLossModelBuildPoints_Speed_Lab": 4, "ModelBuildGammaDistribution_Lab": 1, "MagLossCoeff_MotorLAB": 1.961416686, "XEndLeak_MotorLAB": 1.0, "BrTempCoeff_MotorLAB": -0.152201067761, "MaxMagnet_MotorLAB": 140.0, "MagnetLossCalc_Lab": 3, "IronLossCalc_Lab": 3, "Tmag_MotorLAB": 65.0, "Ld_MotorLAB": 0.000177569943091, "Lq_MotorLAB": 0.000377775325555, "LamM_MotorLAB": 0.0664977490569, "Isc_MotorLAB": 333.3210673, "LEndWdg_MotorLAB": 0.0, "Vdrop_MotorLAB": "True", "SyncRel_MotorLAB": "False", "UseMagnetTempLinkMethod_Lab": 1, "MagnetTempLinkMethod": 1, "ControlStrat_MotorLAB": 0, "NumControlStrategyPoints_Lab": 3, "StatorCurrentLimit_Lab": 1, "InitialCurrentMethod_Lab": 2, "PowerLimVal_MotorLAB": 0.0, "PowerLim_MotorLAB": "False", "TmagnetCalc_MotorLAB": 65.0, "MagnetLossBuildFactor": 1.0, "SmoothMap_MotorLAB": "True", "psiQ_coeff_MotorLAB": [-1.22459892871e-05, 3.34643823614e-06, 0.000734275638415, 7.72218232657e-09, 1.34719426451e-07, -1.12352185242e-06, -5.21543393588e-10, -1.95539099677e-09, -8.07630141653e-10, 4.85923773117e-13, 2.93356614477e-12, 2.42672711631e-12], "psiD_coeff_MotorLAB": [0.0762214253879, 0.000243247674634, 1.01959934716e-05, 4.37265613089e-08, -2.55805901475e-08, -5.7053314445e-08, -1.95996475722e-10, -1.07471703618e-09, -4.0166792834e-10, -7.54451200575e-14, 1.43540494391e-12, 6.85215135725e-13], "SatModelBuildPoints_Lab": 30, "Sync_IrSatModel_Lab": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], "SatModel_Is_Lab": [0.0, 0.0, 0.0, 0.0, 0.0, 96.0, 96.0, 96.0, 96.0, 96.0, 192.0, 192.0, 192.0, 192.0, 192.0, 288.0, 288.0, 288.0, 288.0, 288.0, 384.0, 384.0, 384.0, 384.0, 384.0, 480.0, 480.0, 480.0, 480.0, 480.0], "SatModel_Gamma_Lab": [0.0, 22.5, 45.0, 67.5, 90.0, 0.0, 22.5, 45.0, 67.5, 90.0, 0.0, 22.5, 45.0, 67.5, 90.0, 0.0, 22.5, 45.0, 67.5, 90.0, 0.0, 22.5, 45.0, 67.5, 90.0, 0.0, 22.5, 45.0, 67.5, 90.0], "SatModel_Speed_Lab": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], "PsiDModel_Lab": [0.076206425986, 0.076206425986, 0.076206425986, 0.076206425986, 0.076206425986, 0.0763321414227, 0.0679775525481, 0.0605382026668, 0.0552906772754, 0.053393511108, 0.0739172309381, 0.0595680613023, 0.0460835098095, 0.0353620136839, 0.0312643329067, 0.0691252856761, 0.0500301452396, 0.0320625529695, 0.0165043274227, 0.00986045001583, 0.0642515605719, 0.0407548193678, 0.0186153849175, -0.00146278671755, -0.0109561701507, 0.0598126311322, 0.0323386241814, 0.00622435185344, -0.0178819642463, -0.0303377240366], "PsiQModel_Lab": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0602502440555, 0.0561261666734, 0.043451228691, 0.0236408001234, 0.0, 0.0966505140769, 0.0947761413556, 0.0792258151143, 0.044919540751, 0.0, 0.114216909685, 0.115570705983, 0.103274932649, 0.0632243984501, 0.0, 0.124976371115, 0.127877730111, 0.118434219501, 0.0781238190327, 0.0, 0.132591636006, 0.13612555371, 0.128094538877, 0.089623037544, 0.0], "TorqueRippleModel_Lab": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], "FeLossBackIronHy_MotorLAB": [0.196727537839, 0.196727537839, 0.196727537839, 0.196727537839, 0.196727537839, 0.323525981935, 0.267505229007, 0.202742548826, 0.146613272543, 0.121368536254, 0.507534286613, 0.41477192526, 0.266830238023, 0.131540290126, 0.0685629185636, 0.649648360395, 0.567064256156, 0.404244813725, 0.178334489473, 0.0380403490566, 0.738593554774, 0.67317344289, 0.541056645591, 0.274481320721, 0.0759612773855, 0.785984873327, 0.739451715237, 0.640485407686, 0.38526188494, 0.140939644213], "FeLossBackIronEd_MotorLAB": [0.000379124045658, 0.000379124045658, 0.000379124045658, 0.000379124045658, 0.000379124045658, 0.000607197386403, 0.000506066731905, 0.000386152405939, 0.000286728213861, 0.000245164894877, 0.00103348359848, 0.000836363694342, 0.000569202363951, 0.000312338237233, 0.000201102936379, 0.0013545171305, 0.00114512058289, 0.000809345201739, 0.000420512973159, 0.000233172364584, 0.0015691374296, 0.00138381756577, 0.00107418369282, 0.000582498077389, 0.000329216305125, 0.00172269514129, 0.00158320425878, 0.00129633582313, 0.000783006192103, 0.000459060944012], "FeLossToothHy_MotorLAB": [0.185412552243, 0.185412552243, 0.185412552243, 0.185412552243, 0.185412552243, 0.379115631661, 0.364289322081, 0.342049956623, 0.28841045513, 0.213277465728, 0.478478016276, 0.469333399324, 0.438679223867, 0.448201666152, 0.244290187976, 0.512785024242, 0.508480505048, 0.493498654718, 0.498180574212, 0.214211814093, 0.532741202253, 0.526764153942, 0.515350677609, 0.570318624799, 0.376962952345, 0.548118476396, 0.539355378576, 0.526658495085, 0.563132542256, 0.54761204866], "FeLossToothEd_MotorLAB": [0.000668873138897, 0.000668873138897, 0.000668873138897, 0.000668873138897, 0.000668873138897, 0.000820841435781, 0.000812762888633, 0.000838583840157, 0.000863054537206, 0.000854206201285, 0.0011829420831, 0.00107397049151, 0.00104543944777, 0.00121690076287, 0.00125101448227, 0.00151800219289, 0.00134902270132, 0.0012273852385, 0.00160623552182, 0.00181186405062, 0.00181343534685, 0.00165194354909, 0.00151230047755, 0.00189286115604, 0.00247961623565, 0.00201795493131, 0.00192851768946, 0.00178966741232, 0.00204775369452, 0.00309386460603], "FeLossRotorHy_MotorLAB": [0.000222171765457, 0.000222171765457, 0.000222171765457, 0.000222171765457, 0.000222171765457, 0.000506923751175, 0.000332091446786, 0.000261060931059, 0.000175625746203, 0.000173049583879, 0.000853029516709, 0.000279784214111, 0.000190333244912, 0.000214602058339, 0.000262389426499, 0.000399080681467, 0.000210824627608, 0.000125016317998, 0.000221224284766, 0.000706349987257, 0.000272667888211, 0.0002929621569, 0.000124113953653, 0.000320539109744, 0.00120738457134, 0.000512615154623, 0.000619078679594, 0.000271244321923, 0.000369468174263, 0.00144030017325], "FeLossRotorEd_MotorLAB": [3.30353507499e-07, 3.30353507499e-07, 3.30353507499e-07, 3.30353507499e-07, 3.30353507499e-07, 2.88613410829e-06, 1.88369501827e-06, 9.28466399633e-07, 4.82257044862e-07, 3.15024275647e-07, 1.78749065141e-06, 1.28235291029e-06, 6.39887229603e-07, 1.08619608246e-06, 9.34884478864e-07, 4.20202705857e-07, 3.19492608847e-07, 4.16630444096e-07, 2.28039418503e-06, 2.58908139689e-06, 3.38973467727e-07, 3.81899807657e-07, 5.48008095992e-07, 3.08807675076e-06, 5.60506835199e-06, 8.12681805712e-07, 8.05218944056e-07, 6.18854132514e-07, 6.33562588365e-06, 9.92946175491e-06], "FeLossRotorPoleHy_MotorLAB": [0.00522674027624, 0.00522674027624, 0.00522674027624, 0.00522674027624, 0.00522674027624, 0.0101867311086, 0.00857241201502, 0.00740518098735, 0.00575631256357, 0.00556989900347, 0.0151304266772, 0.0121009126506, 0.00907784293836, 0.00655407817757, 0.00589789522883, 0.0155155953358, 0.0124218478922, 0.0117124272, 0.00859917987867, 0.00862213627183, 0.0159750071332, 0.0140022618604, 0.0128861404546, 0.0105702358433, 0.011701772557, 0.0142994441299, 0.0140716715319, 0.013416517844, 0.0131107329323, 0.0147551017292], "FeLossRotorPoleEd_MotorLAB": [6.68453533697e-05, 6.68453533697e-05, 6.68453533697e-05, 6.68453533697e-05, 6.68453533697e-05, 0.000119233714639, 9.75138503054e-05, 7.46706304036e-05, 5.99110448235e-05, 5.31187673207e-05, 0.000187825463245, 0.000158132642187, 0.000117340113471, 8.40494033743e-05, 7.46840199751e-05, 0.000232857420553, 0.000208294370327, 0.000176901551561, 0.000138783019551, 0.000126265977775, 0.000260683482131, 0.000240471594752, 0.000231895097549, 0.000207985108723, 0.000205631284812, 0.000280887550993, 0.000262346554555, 0.000264881941407, 0.000284821554006, 0.000287087155144], "FeHysLossArray_MotorLAB": [0.387589002123, 0.387589002123, 0.387589002123, 0.387589002123, 0.387589002123, 0.713335268456, 0.640699054549, 0.552458747367, 0.440955665983, 0.34038895057, 1.00199575908, 0.896486021449, 0.714777638073, 0.586510636514, 0.319013391195, 1.17834806065, 1.08817743372, 0.909580911961, 0.685335467849, 0.261580649408, 1.28758243205, 1.21423282085, 1.06941757761, 0.855690720473, 0.465833386859, 1.34891540901, 1.29349784402, 1.18083166494, 0.961874628303, 0.704747094776], "FeEddyLossArray_MotorLAB": [0.00111517289143, 0.00111517289143, 0.00111517289143, 0.00111517289143, 0.00111517289143, 0.00155015867093, 0.00141822716586, 0.0013003353429, 0.00121017605294, 0.00115280488776, 0.00240603863548, 0.00206974918095, 0.00173262181242, 0.00161437459956, 0.0015277363231, 0.00310579694665, 0.00270275714715, 0.00221404862225, 0.00216781190871, 0.00217389147438, 0.00364359523205, 0.00327661460942, 0.00281892727601, 0.0026864324189, 0.00302006889394, 0.00402235030541, 0.00377487372174, 0.00335150403099, 0.00312191706651, 0.00384994216694], "MagLossArray_MotorLAB": [0.000573114279789, 0.000573114279789, 0.000573114279789, 0.000573114279789, 0.000573114279789, 0.00120216616567, 0.00148364616294, 0.00145150769075, 0.00100078918982, 0.000823725139978, 0.00180061522866, 0.00180248448899, 0.00266716350544, 0.0016777749922, 0.00135118081687, 0.00507071446861, 0.00449948060915, 0.0056880741092, 0.003093185807, 0.00166828483994, 0.0138822975515, 0.00818696146924, 0.00769071882756, 0.00726864496615, 0.00230662615003, 0.0385219715283, 0.0255680110063, 0.0100252164884, 0.0202010377965, 0.00940226565262], "WindageLossMap_NumSpeeds": 10, "WindageLossMap_NumTemps": 5, "WindageLossMap_Speeds": [0.0, 1111.111111111111, 2222.222222222222, 3333.333333333333, 4444.444444444444, 5555.555555555556, 6666.666666666666, 7777.777777777777, 8888.888888888889, 10000.0], "WindageLossMap_Temps": [0.0, 50.0, 100.0, 150.0, 200.0], "WindageLossMap_Losses": [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], "BearingLossMap_NumSpeeds": 10, "BearingLossMap_NumTemps": 5, "BearingLossMap_Speeds": [0.0, 1111.111111111111, 2222.222222222222, 3333.333333333333, 4444.444444444444, 5555.555555555556, 6666.666666666666, 7777.777777777777, 8888.888888888889, 10000.0], "BearingLossMap_Temps": [0.0, 50.0, 100.0, 150.0, 200.0], "BearingLossMap_Losses": [0.0, 0.0, 0.0, 0.0, 0.0, 2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778, 5.55555555555555, 5.55555555555555, 5.55555555555555, 5.55555555555555, 5.55555555555555, 8.33333333333335, 8.33333333333335, 8.33333333333335, 8.33333333333335, 8.33333333333335, 11.1111111111111, 11.1111111111111, 11.1111111111111, 11.1111111111111, 11.1111111111111, 13.8888888888889, 13.8888888888889, 13.8888888888889, 13.8888888888889, 13.8888888888889, 16.66666666666665, 16.66666666666665, 16.66666666666665, 16.66666666666665, 16.66666666666665, 19.44444444444445, 19.44444444444445, 19.44444444444445, 19.44444444444445, 19.44444444444445, 22.2222222222222, 22.2222222222222, 22.2222222222222, 22.2222222222222, 22.2222222222222, 25.0, 25.0, 25.0, 25.0, 25.0]} \ No newline at end of file diff --git a/tests/integration/test_optislang_integration.py b/tests/integration/test_optislang_integration.py index 4af35f09..3027eb78 100644 --- a/tests/integration/test_optislang_integration.py +++ b/tests/integration/test_optislang_integration.py @@ -131,7 +131,6 @@ def project_name(): @pytest.fixture def created_project(client, account_id, hpc_id, token, project_name): - created_project = app.create_new_project(client, account_id, hpc_id, f"{project_name}") yield created_project app.delete_project(created_project["projectId"], token) @@ -253,7 +252,6 @@ def test_accounts(accounts, token): def test_hpc_endpoint(hpc_id): - assert isinstance(hpc_id, str) assert len(hpc_id) > 0, "HPC ID should not be empty" @@ -306,7 +304,125 @@ def test_project_ids(project_ids, project_id, project_name): assert project_id in project_ids[project_name] -# data_types ????? -# posted_data = app.post(client, f"/{data_type}", data=data) +@pytest.fixture +def transmission_loss_coefficients(client_with_design_instance): + """Fixture to provide transmission loss coefficients.""" + transmission = { + "component_type": "TransmissionLossCoefficients", + } + return app.post(client_with_design_instance, "/components", data=transmission) + + +@pytest.fixture +def aero(client_with_design_instance): + """Fixture to provide aero configuration.""" + aero = { + "config_type": "aero", + } + return app.post(client_with_design_instance, "/configurations", data=aero) + + +@pytest.fixture +def mass(client_with_design_instance): + """Fixture to provide mass configuration.""" + mass = { + "config_type": "mass", + } + return app.post(client_with_design_instance, "/configurations", data=mass) + + +@pytest.fixture +def wheel(client_with_design_instance): + """Fixture to provide wheel configuration.""" + wheel = { + "config_type": "wheel", + } + return app.post(client_with_design_instance, "/configurations", data=wheel) + + +@pytest.fixture +def requirement(client_with_design_instance, aero, mass, wheel): + requirement = { + "requirement_type": "static_acceleration", + "speed": 10, + "mass_id": mass["id"], + "aero_id": aero["id"], + "wheel_id": wheel["id"], + "state_of_charge": 0.75, + "acceleration": 0.5, + } + requirement = app.post(client_with_design_instance, "/requirements", data=requirement) + return requirement + + +@pytest.fixture +def motor_file(client_with_design_instance): + """Fixture to provide a motor configuration.""" + motor_filename = "./e9.lab" + return app.post_component_file( + client_with_design_instance, motor_filename, component_file_type="motor_lab_file" + ) + + +@pytest.fixture +def motor(client_with_design_instance): + """Fixture to provide a battery configuration.""" + motor = { + "component_type": "MotorCTCP", + "name": "Test Motor", + "rated_power": 150000, + "stall_torque": 300, + "max_speed": 300, + "voltage": 400, + } + return app.post(client_with_design_instance, "/components", data=motor) + + +@pytest.fixture +def battery(client_with_design_instance): + """Fixture to provide a battery configuration.""" + battery = {"component_type": "BatteryFixedVoltages"} + return app.post(client_with_design_instance, "/components", data=battery) + + +@pytest.fixture +def architecture(client_with_design_instance, transmission_loss_coefficients, motor, battery): + architecture = { + "number_of_front_motors": 1, + "number_of_front_wheels": 2, + "number_of_rear_motors": 0, + "number_of_rear_wheels": 2, + "front_transmission_id": transmission_loss_coefficients["id"], + "front_motor_id": motor["id"], + "battery_id": battery["id"], + } + architecture = app.post(client_with_design_instance, "/architectures", data=architecture) + return architecture + + +def test_configuration(aero): + """Test creating an aero configuration.""" + assert aero + assert aero["config_type"] == "aero" + assert "id" in aero + + +def test_component(transmission_loss_coefficients): + assert transmission_loss_coefficients + assert "id" in transmission_loss_coefficients + + +def test_create_requirement(requirement): + assert requirement + assert "id" in requirement + + +def test_architecture(architecture): + """Test creating an architecture.""" + assert architecture + assert "id" in architecture + -# created_component = app.post_component_file(client, str(filepath), component_type) +def test_create_from_file(motor_file): + assert isinstance(motor_file, list) + assert len(motor_file) == 2 From 29a4c3730f6bafaf2585e2fbf34ea2fed2544c97 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 10:55:45 +0100 Subject: [PATCH 07/38] added pyoptislang test --- poetry.lock | 2 +- pyproject.toml | 2 +- tests/e2e/test_optislang_e2e.py | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/poetry.lock b/poetry.lock index 0ebedd26..d99ff590 100644 --- a/poetry.lock +++ b/poetry.lock @@ -5282,4 +5282,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4.0" -content-hash = "c019e170f77e148a78ed9521daaf4563e1ad4f7a40de9af647e5b05b7c7f2bfd" +content-hash = "b1dcd176676ac34a8e1dcf8ce8ad4fda71507edf5ccd930b42d8510a6eae3718" diff --git a/pyproject.toml b/pyproject.toml index b31f394a..9c0c5b4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,7 +87,7 @@ pytest-mock = "^3.12.0" # Optional build requirements pytest-asyncio = ">=0.24,<1.1" -ansys-optislang-core = ">=0.10,<1.1" +ansys-optislang-core = "^1.0.0" [tool.poetry.group.build] optional = true diff --git a/tests/e2e/test_optislang_e2e.py b/tests/e2e/test_optislang_e2e.py index 137a8e68..f8f49c34 100644 --- a/tests/e2e/test_optislang_e2e.py +++ b/tests/e2e/test_optislang_e2e.py @@ -140,7 +140,7 @@ def test_optislang_connection() -> None: # created concept # configure environment design_instance_id = "7a906ce3-76ad-49ce-b707-ac38e4efdcbd" # Need a completed job? - osl = Optislang(loglevel="DEBUG", project_path=osl_project_path) + osl = Optislang(project_path=osl_project_path) print(osl) osl.osl_server.timeouts_register.default_value = 180 std_handler, err_handler = prepare_logging_facilities(osl, working_dir) @@ -171,20 +171,20 @@ def test_optislang_connection() -> None: register_parameter(cev_node, "rear_motor") register_response(cev_node, "_00__capability_curve__torque_vs_speed") - register_response(cev_node, "_01__summary__cost") - register_response(cev_node, "_01__summary__mass") - register_response(cev_node, "_01__summary__constraints_fulfilled") - register_response(cev_node, "_01__summary__n_constraints_fulfilled") + register_response(cev_node, "_02__summary__cost") + register_response(cev_node, "_02__summary__mass") + register_response(cev_node, "_02__summary__constraints_fulfilled") + register_response(cev_node, "_02__summary__n_constraints_fulfilled") sensitivity.criteria_manager.add_criterion( ObjectiveCriterion( - name="obj_cost", expression="_01__summary__cost", criterion=ComparisonType.MIN + name="obj_cost", expression="_02__summary__cost", criterion=ComparisonType.MIN ) ) sensitivity.criteria_manager.add_criterion( ConstraintCriterion( name="constraints_fulfilled", - expression="_01__summary__n_constraints_fulfilled", + expression="_02__summary__n_constraints_fulfilled", criterion=ComparisonType.GREATEREQUAL, limit_expression="1", ) From 88826f9cca283b485a72cf8a212f57e90cdb66e7 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 11:47:37 +0100 Subject: [PATCH 08/38] update to test workflow --- .github/workflows/ci_cd.yml | 13 +++++++++++++ tests/e2e/test_optislang_e2e.py | 7 ++----- tests/integration/test_optislang_integration.py | 5 +++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 01627872..15f1c154 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -155,6 +155,19 @@ jobs: with: python-version: ${{ env.MAIN_PYTHON_VERSION }} pytest-extra-args: "-s -m integration --log-cli-level=INFO" + tests-e2e: + name: E2E Tests + runs-on: ubuntu-latest + needs: [ tests ] + steps: + - uses: ansys/actions/tests-pytest@v10 + env: + PYCONCEPTEV_SETTINGS: "tests/config.toml" + CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} + POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} + with: + python-version: ${{ env.MAIN_PYTHON_VERSION }} + pytest-extra-args: "-s -m e2e --log-cli-level=INFO" doc-build: name: Build documentation runs-on: ubuntu-latest diff --git a/tests/e2e/test_optislang_e2e.py b/tests/e2e/test_optislang_e2e.py index f8f49c34..deeb3655 100644 --- a/tests/e2e/test_optislang_e2e.py +++ b/tests/e2e/test_optislang_e2e.py @@ -24,11 +24,6 @@ import os import shutil -# from ansys.optislang.core import Optislang -# from ansys.optislang.core import examples -# from ansys.optislang.core import Optislang -# from ansys.optislang.core.nodes import DesignFlow -# import ansys.optislang.core.node_types as node_types from ansys.optislang.core import Optislang import ansys.optislang.core.node_types as node_types from ansys.optislang.core.nodes import DesignFlow @@ -37,6 +32,7 @@ ConstraintCriterion, ObjectiveCriterion, ) +import pytest class QueryHandler(logging.Handler): @@ -126,6 +122,7 @@ def remove_non_empty_dir(path): shutil.rmtree(path, ignore_errors=False, onerror=None) +@pytest.mark.e2e def test_optislang_connection() -> None: # create fresh working directory # this is logging in interactively and connecting to prod server at the moment diff --git a/tests/integration/test_optislang_integration.py b/tests/integration/test_optislang_integration.py index 3027eb78..b980a66e 100644 --- a/tests/integration/test_optislang_integration.py +++ b/tests/integration/test_optislang_integration.py @@ -400,6 +400,7 @@ def architecture(client_with_design_instance, transmission_loss_coefficients, mo return architecture +@pytest.mark.integration def test_configuration(aero): """Test creating an aero configuration.""" assert aero @@ -407,22 +408,26 @@ def test_configuration(aero): assert "id" in aero +@pytest.mark.integration def test_component(transmission_loss_coefficients): assert transmission_loss_coefficients assert "id" in transmission_loss_coefficients +@pytest.mark.integration def test_create_requirement(requirement): assert requirement assert "id" in requirement +@pytest.mark.integration def test_architecture(architecture): """Test creating an architecture.""" assert architecture assert "id" in architecture +@pytest.mark.integration def test_create_from_file(motor_file): assert isinstance(motor_file, list) assert len(motor_file) == 2 From dea4cdee8142a3df8f4fe7bd8be4f62de5d8f1c6 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 12:05:51 +0100 Subject: [PATCH 09/38] update lock file after merge --- poetry.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index d99ff590..0e3d7808 100644 --- a/poetry.lock +++ b/poetry.lock @@ -5282,4 +5282,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4.0" -content-hash = "b1dcd176676ac34a8e1dcf8ce8ad4fda71507edf5ccd930b42d8510a6eae3718" +content-hash = "d3f1fefe3edb29512a747ad2921b5ced2ba69d51834312aeda3bff92c6eac6c2" From 1b5a2ba9896d743aa53099910b74903db730d453 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Thu, 10 Jul 2025 11:10:59 +0000 Subject: [PATCH 10/38] chore: adding changelog file 261.miscellaneous.md [dependabot-skip] --- doc/changelog.d/261.miscellaneous.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/changelog.d/261.miscellaneous.md diff --git a/doc/changelog.d/261.miscellaneous.md b/doc/changelog.d/261.miscellaneous.md new file mode 100644 index 00000000..5cb4f9be --- /dev/null +++ b/doc/changelog.d/261.miscellaneous.md @@ -0,0 +1 @@ +Feature/optislang integration test \ No newline at end of file From 1baa9eb8c432b302f9c6ed2e8e93ea20c45e1619 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 16:49:38 +0100 Subject: [PATCH 11/38] moved and fixed up some tests --- tests/e2e/test_optislang_e2e.py | 4 ++-- tests/integration/config.toml | 9 --------- tests/integration/test_optislang_integration.py | 6 +++--- tests/old_config.toml | 8 -------- tests/{ => unit}/test_app.py | 0 tests/{ => unit}/test_auth.py | 0 tests/{ => unit}/test_metadata.py | 0 tests/{ => unit}/test_ocm.py | 0 tests/{ => unit}/test_progress.py | 0 tests/{ => unit}/test_settings.py | 2 -- 10 files changed, 5 insertions(+), 24 deletions(-) delete mode 100644 tests/integration/config.toml delete mode 100644 tests/old_config.toml rename tests/{ => unit}/test_app.py (100%) rename tests/{ => unit}/test_auth.py (100%) rename tests/{ => unit}/test_metadata.py (100%) rename tests/{ => unit}/test_ocm.py (100%) rename tests/{ => unit}/test_progress.py (100%) rename tests/{ => unit}/test_settings.py (96%) diff --git a/tests/e2e/test_optislang_e2e.py b/tests/e2e/test_optislang_e2e.py index deeb3655..ccaf1da0 100644 --- a/tests/e2e/test_optislang_e2e.py +++ b/tests/e2e/test_optislang_e2e.py @@ -136,7 +136,7 @@ def test_optislang_connection() -> None: # created concept # configure environment - design_instance_id = "7a906ce3-76ad-49ce-b707-ac38e4efdcbd" # Need a completed job? + design_instance_id = "121222c8-f2e8-4fa2-84fb-69336bbdc548" osl = Optislang(project_path=osl_project_path) print(osl) osl.osl_server.timeouts_register.default_value = 180 @@ -156,7 +156,7 @@ def test_optislang_connection() -> None: design_flow=DesignFlow.RECEIVE_SEND, ) non_modifying_settings = cev_node.get_property("NonModifyingSettings") - non_modifying_settings["cev_account_name"] = "conceptev_saas@ansys.com" + non_modifying_settings["cev_account_name"] = "ConceptEv Test Account" cev_node.set_property("NonModifyingSettings", non_modifying_settings) modifying_settings = cev_node.get_property("ModifyingSettings") modifying_settings["cev_concept_id"] = design_instance_id diff --git a/tests/integration/config.toml b/tests/integration/config.toml deleted file mode 100644 index bf043ca6..00000000 --- a/tests/integration/config.toml +++ /dev/null @@ -1,9 +0,0 @@ -OCM_URL = "https://dev.portal.onscale.com/api" -OCM_SOCKET_URL = "wss://sockets.dev.portal.onscale.com/socket" -CONCEPTEV_URL = "https://test-conceptev.awsansys3np.onscale.com/api" -client_id = "9c9edb71-06f9-4c4b-afed-9201668385de" -authority = "https://a365dev.b2clogin.com/a365dev.onmicrosoft.com/b2c_1a_ansysid_signup_signin_test" -scope = "https://a365dev.onmicrosoft.com/AnsysID/Authentication" -conceptev_username = "conceptev_testing@ansys.com" -account_name = "ConceptEv Test Account" -job_timeout = 3600 \ No newline at end of file diff --git a/tests/integration/test_optislang_integration.py b/tests/integration/test_optislang_integration.py index b980a66e..b9d9411c 100644 --- a/tests/integration/test_optislang_integration.py +++ b/tests/integration/test_optislang_integration.py @@ -26,7 +26,7 @@ import jwt # Optislang Integration Test -# A poor mans integration test for the optislang integration. +# A poor attempt at integration test for the optislang integration. # Looks at conceptev/utils/api_helper.py to see pyconceptev usage within ConceptEV integration. import pytest @@ -265,7 +265,7 @@ def test_submit_job(job_info): def test_read_results(read_results): """Test reading results from the job.""" assert isinstance(read_results, list) - assert read_results[0]["feasible"] == True + assert read_results[0]["feasible"] == False assert len(read_results) > 0, "Results should not be empty" @@ -358,7 +358,7 @@ def requirement(client_with_design_instance, aero, mass, wheel): @pytest.fixture def motor_file(client_with_design_instance): """Fixture to provide a motor configuration.""" - motor_filename = "./e9.lab" + motor_filename = "./integration/e9.lab" return app.post_component_file( client_with_design_instance, motor_filename, component_file_type="motor_lab_file" ) diff --git a/tests/old_config.toml b/tests/old_config.toml deleted file mode 100644 index 7721ab56..00000000 --- a/tests/old_config.toml +++ /dev/null @@ -1,8 +0,0 @@ -OCM_URL = "https://dev.portal.onscale.com/api" -OCM_SOCKET_URL = "wss://sockets.dev.portal.onscale.com/socket" -CONCEPTEV_URL = "https://test-conceptev.awsansys3np.onscale.com/api" -client_id = "9c9edb71-06f9-4c4b-afed-9201668385de" -authority = "https://a365dev.b2clogin.com/a365dev.onmicrosoft.com/b2c_1a_ansysid_signup_signin_test" -scope = "https://a365dev.onmicrosoft.com/AnsysID/Authentication" -conceptev_username = "conceptev_testing@ansys.com" -account_name = "ConceptEv Test Account" \ No newline at end of file diff --git a/tests/test_app.py b/tests/unit/test_app.py similarity index 100% rename from tests/test_app.py rename to tests/unit/test_app.py diff --git a/tests/test_auth.py b/tests/unit/test_auth.py similarity index 100% rename from tests/test_auth.py rename to tests/unit/test_auth.py diff --git a/tests/test_metadata.py b/tests/unit/test_metadata.py similarity index 100% rename from tests/test_metadata.py rename to tests/unit/test_metadata.py diff --git a/tests/test_ocm.py b/tests/unit/test_ocm.py similarity index 100% rename from tests/test_ocm.py rename to tests/unit/test_ocm.py diff --git a/tests/test_progress.py b/tests/unit/test_progress.py similarity index 100% rename from tests/test_progress.py rename to tests/unit/test_progress.py diff --git a/tests/test_settings.py b/tests/unit/test_settings.py similarity index 96% rename from tests/test_settings.py rename to tests/unit/test_settings.py index 13cb48ba..1b0075ae 100644 --- a/tests/test_settings.py +++ b/tests/unit/test_settings.py @@ -21,14 +21,12 @@ # SOFTWARE. import os -from pathlib import Path from ansys.conceptev.core.settings import Settings def test_settings(): os.environ["ACCOUNT_NAME"] = "borked" - os.chdir(Path(__file__).parent) settings = Settings() assert settings.job_timeout == 3600 # from resources assert settings.ocm_url == "https://dev.portal.onscale.com/api" # from working directory From 2a129dc64f7716636a0b9b32eb64968e7e38a290 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:51:26 +0000 Subject: [PATCH 12/38] chore: adding changelog file 261.maintenance.md [dependabot-skip] --- doc/changelog.d/{261.miscellaneous.md => 261.maintenance.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/changelog.d/{261.miscellaneous.md => 261.maintenance.md} (100%) diff --git a/doc/changelog.d/261.miscellaneous.md b/doc/changelog.d/261.maintenance.md similarity index 100% rename from doc/changelog.d/261.miscellaneous.md rename to doc/changelog.d/261.maintenance.md From 4c6beb2ae1d606909c31757bf48c437c50c34378 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 16:52:50 +0100 Subject: [PATCH 13/38] update to pipeline --- .github/workflows/ci_cd.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 15f1c154..6e2dd9cb 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -125,7 +125,7 @@ jobs: CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} with: - pytest-extra-args: "-m 'not integration' --cov=ansys --cov-report=term --cov-report=html:.cov/html" + pytest-extra-args: "unit --cov=ansys --cov-report=term --cov-report=html:.cov/html" - name: Upload coverage results uses: actions/upload-artifact@v4 @@ -154,7 +154,7 @@ jobs: POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} with: python-version: ${{ env.MAIN_PYTHON_VERSION }} - pytest-extra-args: "-s -m integration --log-cli-level=INFO" + pytest-extra-args: "integration" tests-e2e: name: E2E Tests runs-on: ubuntu-latest @@ -167,7 +167,7 @@ jobs: POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} with: python-version: ${{ env.MAIN_PYTHON_VERSION }} - pytest-extra-args: "-s -m e2e --log-cli-level=INFO" + pytest-extra-args: "e2e" doc-build: name: Build documentation runs-on: ubuntu-latest From a0586b479c45300b6e9a85771f3878371b6e0786 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 16:59:58 +0100 Subject: [PATCH 14/38] trying to get optislang from container --- .github/workflows/ci_cd.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 6e2dd9cb..a1c910a8 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -159,15 +159,21 @@ jobs: name: E2E Tests runs-on: ubuntu-latest needs: [ tests ] + container: + image: ${{ format('ghcr.io/ansys/optislang:{0}-jammy', '25.2.0') }} + credentials: + username: ansys-bot + password: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: ansys/actions/tests-pytest@v10 + - name: "Pytest" env: - PYCONCEPTEV_SETTINGS: "tests/config.toml" - CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} - POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} + PYOPTISLANG_DISABLE_OPTISLANG_OUTPUT: true + ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} + uses: ansys/actions/tests-pytest@v10 with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} + python-version: "3.13" pytest-extra-args: "e2e" + use-python-cache: false doc-build: name: Build documentation runs-on: ubuntu-latest From 5aa2404eb3b6a63d79b91256b0565b2ef559c5ae Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 17:01:58 +0100 Subject: [PATCH 15/38] updated path to tests --- .github/workflows/ci_cd.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index a1c910a8..1e31b44a 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -125,7 +125,7 @@ jobs: CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} with: - pytest-extra-args: "unit --cov=ansys --cov-report=term --cov-report=html:.cov/html" + pytest-extra-args: "tests/unit --cov=ansys --cov-report=term --cov-report=html:.cov/html" - name: Upload coverage results uses: actions/upload-artifact@v4 @@ -154,7 +154,7 @@ jobs: POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} with: python-version: ${{ env.MAIN_PYTHON_VERSION }} - pytest-extra-args: "integration" + pytest-extra-args: "tests/integration" tests-e2e: name: E2E Tests runs-on: ubuntu-latest @@ -172,7 +172,7 @@ jobs: uses: ansys/actions/tests-pytest@v10 with: python-version: "3.13" - pytest-extra-args: "e2e" + pytest-extra-args: "tests/e2e" use-python-cache: false doc-build: name: Build documentation From 4e7375c5ef7d43c9916d37a015ab909a4fb9c9d1 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 17:26:03 +0100 Subject: [PATCH 16/38] moved an integration test back into correct folder --- tests/{unit => integration}/test_ocm.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{unit => integration}/test_ocm.py (100%) diff --git a/tests/unit/test_ocm.py b/tests/integration/test_ocm.py similarity index 100% rename from tests/unit/test_ocm.py rename to tests/integration/test_ocm.py From d8c4d164f58fa14141c5608b77fb3f3feef35faf Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 17:47:38 +0100 Subject: [PATCH 17/38] updating test location --- .github/workflows/ci_cd.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 1e31b44a..2835ecfc 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -125,7 +125,8 @@ jobs: CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} with: - pytest-extra-args: "tests/unit --cov=ansys --cov-report=term --cov-report=html:.cov/html" + path: "tests" + pytest-extra-args: "unit --cov=ansys --cov-report=term --cov-report=html:.cov/html" - name: Upload coverage results uses: actions/upload-artifact@v4 @@ -153,8 +154,9 @@ jobs: CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} with: + path: "tests" python-version: ${{ env.MAIN_PYTHON_VERSION }} - pytest-extra-args: "tests/integration" + pytest-extra-args: "integration" tests-e2e: name: E2E Tests runs-on: ubuntu-latest @@ -171,8 +173,9 @@ jobs: ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} uses: ansys/actions/tests-pytest@v10 with: + path: "tests" python-version: "3.13" - pytest-extra-args: "tests/e2e" + pytest-extra-args: "e2e" use-python-cache: false doc-build: name: Build documentation From 82ac4b820e77a429e066c445d1440d1a5f167a00 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 18:55:19 +0100 Subject: [PATCH 18/38] added config to each test folder --- tests/{ => e2e}/config.toml | 0 tests/integration/config.toml | 9 +++++++++ tests/unit/config.toml | 9 +++++++++ 3 files changed, 18 insertions(+) rename tests/{ => e2e}/config.toml (100%) create mode 100644 tests/integration/config.toml create mode 100644 tests/unit/config.toml diff --git a/tests/config.toml b/tests/e2e/config.toml similarity index 100% rename from tests/config.toml rename to tests/e2e/config.toml diff --git a/tests/integration/config.toml b/tests/integration/config.toml new file mode 100644 index 00000000..5c524632 --- /dev/null +++ b/tests/integration/config.toml @@ -0,0 +1,9 @@ +OCM_URL = "https://dev.portal.onscale.com/api" +OCM_SOCKET_URL = "wss://sockets.dev.portal.onscale.com/socket" +CONCEPTEV_URL = "https://test-conceptev.awsansys3np.onscale.com/api" +client_id = "743c94e3-c72d-4ace-b9ee-ab5c3cbe6504" +authority = "https://a365dev.b2clogin.com/a365dev.onmicrosoft.com/b2c_1a_ansysid_signup_signin_test" +scope = "https://a365dev.onmicrosoft.com/AnsysID/Authentication" +conceptev_username = "conceptev_testing@ansys.com" +account_name = "ConceptEv Test Account" +job_timeout = 3600 \ No newline at end of file diff --git a/tests/unit/config.toml b/tests/unit/config.toml new file mode 100644 index 00000000..5c524632 --- /dev/null +++ b/tests/unit/config.toml @@ -0,0 +1,9 @@ +OCM_URL = "https://dev.portal.onscale.com/api" +OCM_SOCKET_URL = "wss://sockets.dev.portal.onscale.com/socket" +CONCEPTEV_URL = "https://test-conceptev.awsansys3np.onscale.com/api" +client_id = "743c94e3-c72d-4ace-b9ee-ab5c3cbe6504" +authority = "https://a365dev.b2clogin.com/a365dev.onmicrosoft.com/b2c_1a_ansysid_signup_signin_test" +scope = "https://a365dev.onmicrosoft.com/AnsysID/Authentication" +conceptev_username = "conceptev_testing@ansys.com" +account_name = "ConceptEv Test Account" +job_timeout = 3600 \ No newline at end of file From 0cb8cfe96d4dbc830b18c7564500fac4cdb57a51 Mon Sep 17 00:00:00 2001 From: pyansys-ci-bot <92810346+pyansys-ci-bot@users.noreply.github.com> Date: Thu, 10 Jul 2025 17:56:31 +0000 Subject: [PATCH 19/38] chore: adding changelog file 261.miscellaneous.md [dependabot-skip] --- doc/changelog.d/{261.maintenance.md => 261.miscellaneous.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/changelog.d/{261.maintenance.md => 261.miscellaneous.md} (100%) diff --git a/doc/changelog.d/261.maintenance.md b/doc/changelog.d/261.miscellaneous.md similarity index 100% rename from doc/changelog.d/261.maintenance.md rename to doc/changelog.d/261.miscellaneous.md From a9c33aac7dee192ad13934a65b582239f3f251bc Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 19:03:28 +0100 Subject: [PATCH 20/38] path option didnt work --- .github/workflows/ci_cd.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 2835ecfc..1e31b44a 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -125,8 +125,7 @@ jobs: CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} with: - path: "tests" - pytest-extra-args: "unit --cov=ansys --cov-report=term --cov-report=html:.cov/html" + pytest-extra-args: "tests/unit --cov=ansys --cov-report=term --cov-report=html:.cov/html" - name: Upload coverage results uses: actions/upload-artifact@v4 @@ -154,9 +153,8 @@ jobs: CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} with: - path: "tests" python-version: ${{ env.MAIN_PYTHON_VERSION }} - pytest-extra-args: "integration" + pytest-extra-args: "tests/integration" tests-e2e: name: E2E Tests runs-on: ubuntu-latest @@ -173,9 +171,8 @@ jobs: ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} uses: ansys/actions/tests-pytest@v10 with: - path: "tests" python-version: "3.13" - pytest-extra-args: "e2e" + pytest-extra-args: "tests/e2e" use-python-cache: false doc-build: name: Build documentation From fd3a8ada3bc6b3c6f1cc50886b6370d01854af19 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 19:09:40 +0100 Subject: [PATCH 21/38] made it use local config --- tests/unit/test_settings.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/test_settings.py b/tests/unit/test_settings.py index 1b0075ae..9461406a 100644 --- a/tests/unit/test_settings.py +++ b/tests/unit/test_settings.py @@ -21,12 +21,14 @@ # SOFTWARE. import os +from pathlib import Path from ansys.conceptev.core.settings import Settings def test_settings(): os.environ["ACCOUNT_NAME"] = "borked" + os.chdir(Path(__file__)) settings = Settings() assert settings.job_timeout == 3600 # from resources assert settings.ocm_url == "https://dev.portal.onscale.com/api" # from working directory From d47759a97b336fe323e87a8d0c4cbd421f6c86e3 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Thu, 10 Jul 2025 19:23:08 +0100 Subject: [PATCH 22/38] make parent of file as thats the directory --- tests/unit/test_settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test_settings.py b/tests/unit/test_settings.py index 9461406a..13cb48ba 100644 --- a/tests/unit/test_settings.py +++ b/tests/unit/test_settings.py @@ -28,7 +28,7 @@ def test_settings(): os.environ["ACCOUNT_NAME"] = "borked" - os.chdir(Path(__file__)) + os.chdir(Path(__file__).parent) settings = Settings() assert settings.job_timeout == 3600 # from resources assert settings.ocm_url == "https://dev.portal.onscale.com/api" # from working directory From e00bd4fc80c6e7414ec271d6252d2bee59efae3a Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 09:07:15 +0100 Subject: [PATCH 23/38] added config variables needed --- .github/workflows/ci_cd.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 1e31b44a..6978b227 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -149,7 +149,7 @@ jobs: steps: - uses: ansys/actions/tests-pytest@v10 env: - PYCONCEPTEV_SETTINGS: "tests/config.toml" + PYCONCEPTEV_SETTINGS: "tests/integration/config.toml" CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} with: @@ -169,6 +169,9 @@ jobs: env: PYOPTISLANG_DISABLE_OPTISLANG_OUTPUT: true ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} + POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} + CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} + PYCONCEPTEV_SETTINGS: "tests/e2e/config.toml" uses: ansys/actions/tests-pytest@v10 with: python-version: "3.13" From 3bc30bed9b2829537d41c3be8c9ac2903c917673 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 11:34:20 +0100 Subject: [PATCH 24/38] update to status retrieval and ci cd config for e2e tests --- .github/workflows/ci_cd.yml | 3 +-- src/ansys/conceptev/core/ocm.py | 2 ++ tests/integration/test_ocm.py | 8 -------- tests/integration/test_optislang_integration.py | 10 ++++------ 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 6978b227..2b70ec74 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -174,9 +174,8 @@ jobs: PYCONCEPTEV_SETTINGS: "tests/e2e/config.toml" uses: ansys/actions/tests-pytest@v10 with: - python-version: "3.13" + python-version: ${{ env.MAIN_PYTHON_VERSION }} pytest-extra-args: "tests/e2e" - use-python-cache: false doc-build: name: Build documentation runs-on: ubuntu-latest diff --git a/src/ansys/conceptev/core/ocm.py b/src/ansys/conceptev/core/ocm.py index df004f59..c6658dd0 100644 --- a/src/ansys/conceptev/core/ocm.py +++ b/src/ansys/conceptev/core/ocm.py @@ -256,6 +256,8 @@ def get_status(job_info: dict, token: str) -> str: status = processed_response["finalStatus"].upper() elif "lastStatus" in processed_response and processed_response["lastStatus"] is not None: status = processed_response["lastStatus"].upper() + elif "jobStatus" in processed_response and processed_response["jobStatus"] is not None: + status = processed_response["jobStatus"][0]["jobStatus"].upper() else: raise ResponseError(f"Failed to get job status {processed_response}.") return status diff --git a/tests/integration/test_ocm.py b/tests/integration/test_ocm.py index 464bfe6a..1a56f9d3 100644 --- a/tests/integration/test_ocm.py +++ b/tests/integration/test_ocm.py @@ -41,21 +41,18 @@ def token(): return token -@pytest.mark.integration def test_product_id(token): """Test product id from OCM.""" product_id = ocm.get_product_id(token) assert product_id == "SAAS000040" -@pytest.mark.integration def test_get_user_id(token): """Test user id from OCM.""" user_id = ocm.get_user_id(token) assert user_id == "95bb6bf9-0afd-4426-b736-7e1c8abd5a78" -@pytest.mark.integration def test_get_account_ids(token): """Test account ids from OCM.""" account_ids = ocm.get_account_ids(token) @@ -65,14 +62,12 @@ def test_get_account_ids(token): } -@pytest.mark.integration def test_get_account_id(token): """Test account ids from OCM.""" account_id = ocm.get_account_id(token) assert account_id == "2a566ece-938d-4658-bae5-ffa387ac0547" -@pytest.mark.integration def test_get_default_hpc(token): """Test default HPC from OCM.""" account_id = "2a566ece-938d-4658-bae5-ffa387ac0547" @@ -80,7 +75,6 @@ def test_get_default_hpc(token): assert hpc_id == "3ded64e3-5a83-24a8-b6e4-9fc30f97a654" -@pytest.mark.integration def test_get_project_ids(token): """Test projects from OCM.""" project_name = "New Project (with brackets)" @@ -91,7 +85,6 @@ def test_get_project_ids(token): assert "00932037-a633-464c-8d05-28353d9bfc49" in project_ids[project_name] -@pytest.mark.integration def test_create_new_project(token): """Test create new project from OCM.""" account_id = "2a566ece-938d-4658-bae5-ffa387ac0547" @@ -105,7 +98,6 @@ def test_create_new_project(token): assert seconds_ago < 10 -@pytest.mark.integration def test_create_new_design(token): """Test create new project from OCM.""" diff --git a/tests/integration/test_optislang_integration.py b/tests/integration/test_optislang_integration.py index b9d9411c..b1503f9f 100644 --- a/tests/integration/test_optislang_integration.py +++ b/tests/integration/test_optislang_integration.py @@ -20,6 +20,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +from pathlib import Path import re import httpx @@ -32,6 +33,8 @@ from ansys.conceptev.core import app, auth, exceptions +DATA_DIR = Path(__file__).parent + @pytest.fixture def msal_app(): @@ -358,7 +361,7 @@ def requirement(client_with_design_instance, aero, mass, wheel): @pytest.fixture def motor_file(client_with_design_instance): """Fixture to provide a motor configuration.""" - motor_filename = "./integration/e9.lab" + motor_filename = DATA_DIR / "e9.lab" return app.post_component_file( client_with_design_instance, motor_filename, component_file_type="motor_lab_file" ) @@ -400,7 +403,6 @@ def architecture(client_with_design_instance, transmission_loss_coefficients, mo return architecture -@pytest.mark.integration def test_configuration(aero): """Test creating an aero configuration.""" assert aero @@ -408,26 +410,22 @@ def test_configuration(aero): assert "id" in aero -@pytest.mark.integration def test_component(transmission_loss_coefficients): assert transmission_loss_coefficients assert "id" in transmission_loss_coefficients -@pytest.mark.integration def test_create_requirement(requirement): assert requirement assert "id" in requirement -@pytest.mark.integration def test_architecture(architecture): """Test creating an architecture.""" assert architecture assert "id" in architecture -@pytest.mark.integration def test_create_from_file(motor_file): assert isinstance(motor_file, list) assert len(motor_file) == 2 From 9ab9510e39d509350ed2be0889886e91b5e84310 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 12:04:50 +0100 Subject: [PATCH 25/38] stopped using uv --- .github/workflows/ci_cd.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 2b70ec74..63f6e73b 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -174,6 +174,7 @@ jobs: PYCONCEPTEV_SETTINGS: "tests/e2e/config.toml" uses: ansys/actions/tests-pytest@v10 with: + use-uv: false python-version: ${{ env.MAIN_PYTHON_VERSION }} pytest-extra-args: "tests/e2e" doc-build: From d14ee88f8fcf111aad67738b12b22396ab263f68 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 12:17:55 +0100 Subject: [PATCH 26/38] updated to ensure pip --- .github/workflows/ci_cd.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 63f6e73b..92599e65 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -165,6 +165,8 @@ jobs: username: ansys-bot password: ${{ secrets.GITHUB_TOKEN }} steps: + - name: Install pip for Python 3.13 + run: python -m ensurepip --upgrade - name: "Pytest" env: PYOPTISLANG_DISABLE_OPTISLANG_OUTPUT: true From c598c13774f0f1c222e85b8855acc305f9c92cd4 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 12:40:01 +0100 Subject: [PATCH 27/38] turn off python cache --- .github/workflows/ci_cd.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 92599e65..bd08a4de 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -165,8 +165,6 @@ jobs: username: ansys-bot password: ${{ secrets.GITHUB_TOKEN }} steps: - - name: Install pip for Python 3.13 - run: python -m ensurepip --upgrade - name: "Pytest" env: PYOPTISLANG_DISABLE_OPTISLANG_OUTPUT: true @@ -179,6 +177,7 @@ jobs: use-uv: false python-version: ${{ env.MAIN_PYTHON_VERSION }} pytest-extra-args: "tests/e2e" + use-python-cache: false doc-build: name: Build documentation runs-on: ubuntu-latest From ac7af6c98e954eec94d0660190a8e151687551e0 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 13:25:03 +0100 Subject: [PATCH 28/38] trying without container --- .github/workflows/ci_cd.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index bd08a4de..c6f06a86 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -159,11 +159,11 @@ jobs: name: E2E Tests runs-on: ubuntu-latest needs: [ tests ] - container: - image: ${{ format('ghcr.io/ansys/optislang:{0}-jammy', '25.2.0') }} - credentials: - username: ansys-bot - password: ${{ secrets.GITHUB_TOKEN }} +# container: +# image: ${{ format('ghcr.io/ansys/optislang:{0}-jammy', '25.2.0') }} +# credentials: +# username: ansys-bot +# password: ${{ secrets.GITHUB_TOKEN }} steps: - name: "Pytest" env: From efa44fec9bf5dc41f01c4ab023b0cc61abb8b7a8 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 13:48:47 +0100 Subject: [PATCH 29/38] trying some different parameters --- .github/workflows/ci_cd.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index c6f06a86..f6b61f34 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -159,17 +159,16 @@ jobs: name: E2E Tests runs-on: ubuntu-latest needs: [ tests ] -# container: -# image: ${{ format('ghcr.io/ansys/optislang:{0}-jammy', '25.2.0') }} -# credentials: -# username: ansys-bot -# password: ${{ secrets.GITHUB_TOKEN }} + container: + image: ${{ format('ghcr.io/ansys/optislang:{0}-jammy', '25.2.0') }} + credentials: + username: ansys-bot + password: ${{ secrets.GITHUB_TOKEN }} steps: - name: "Pytest" env: PYOPTISLANG_DISABLE_OPTISLANG_OUTPUT: true ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} - POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} PYCONCEPTEV_SETTINGS: "tests/e2e/config.toml" uses: ansys/actions/tests-pytest@v10 From 078caaa16e4c341c910ad9db7607f47ae9b09aa7 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 14:00:30 +0100 Subject: [PATCH 30/38] matching ubunutu version --- .github/workflows/ci_cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index f6b61f34..a9cb8cec 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -157,7 +157,7 @@ jobs: pytest-extra-args: "tests/integration" tests-e2e: name: E2E Tests - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 needs: [ tests ] container: image: ${{ format('ghcr.io/ansys/optislang:{0}-jammy', '25.2.0') }} From 71515906131fe4fa54a0688e266b3fd6877ac271 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 14:11:32 +0100 Subject: [PATCH 31/38] made the same as integration tests --- .github/workflows/ci_cd.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index a9cb8cec..3e451874 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -171,12 +171,11 @@ jobs: ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} PYCONCEPTEV_SETTINGS: "tests/e2e/config.toml" + POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} uses: ansys/actions/tests-pytest@v10 with: - use-uv: false python-version: ${{ env.MAIN_PYTHON_VERSION }} pytest-extra-args: "tests/e2e" - use-python-cache: false doc-build: name: Build documentation runs-on: ubuntu-latest From ba36294d4ff2deddfb0a078c7bd2a72516b355ee Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 14:39:49 +0100 Subject: [PATCH 32/38] remove the poetry venv env variable --- .github/workflows/ci_cd.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 3e451874..c1a0fdcd 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -171,7 +171,6 @@ jobs: ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} PYCONCEPTEV_SETTINGS: "tests/e2e/config.toml" - POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} uses: ansys/actions/tests-pytest@v10 with: python-version: ${{ env.MAIN_PYTHON_VERSION }} From 2c9a968db590bb0811b9c098e0f05c8c83d8dae4 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 15:40:59 +0100 Subject: [PATCH 33/38] using old version of pytest to see if its a version issue --- .github/workflows/ci_cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index c1a0fdcd..99a8ec7b 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -171,7 +171,7 @@ jobs: ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} PYCONCEPTEV_SETTINGS: "tests/e2e/config.toml" - uses: ansys/actions/tests-pytest@v10 + uses: ansys/actions/tests-pytest@v9 with: python-version: ${{ env.MAIN_PYTHON_VERSION }} pytest-extra-args: "tests/e2e" From 17478f15bb09f90f14d5617266bf73e98d4789df Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Fri, 11 Jul 2025 15:57:38 +0100 Subject: [PATCH 34/38] back to latest version --- .github/workflows/ci_cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 99a8ec7b..c1a0fdcd 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -171,7 +171,7 @@ jobs: ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} PYCONCEPTEV_SETTINGS: "tests/e2e/config.toml" - uses: ansys/actions/tests-pytest@v9 + uses: ansys/actions/tests-pytest@v10 with: python-version: ${{ env.MAIN_PYTHON_VERSION }} pytest-extra-args: "tests/e2e" From f39998b730eb8bb27fd35b2670a8d6230a688098 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Tue, 15 Jul 2025 09:32:37 +0100 Subject: [PATCH 35/38] poetry virtual envs create environment variable --- .github/workflows/ci_cd.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index c1a0fdcd..3e451874 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -171,6 +171,7 @@ jobs: ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} PYCONCEPTEV_SETTINGS: "tests/e2e/config.toml" + POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} uses: ansys/actions/tests-pytest@v10 with: python-version: ${{ env.MAIN_PYTHON_VERSION }} From b266cd893b7a93c5c3078b094526c8ff7ae53c73 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Tue, 15 Jul 2025 10:39:30 +0100 Subject: [PATCH 36/38] manually install poetry --- .github/workflows/ci_cd.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 3e451874..31eed623 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -165,13 +165,18 @@ jobs: username: ansys-bot password: ${{ secrets.GITHUB_TOKEN }} steps: + - name: "Install Poetry" + uses: snok/install-poetry@v1 + with: + virtualenvs-create: true + virtualenvs-in-project: true + installer-parallel: true - name: "Pytest" env: PYOPTISLANG_DISABLE_OPTISLANG_OUTPUT: true ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER) }} CONCEPTEV_PASSWORD: ${{ secrets.CONCEPTEV_PASSWORD }} PYCONCEPTEV_SETTINGS: "tests/e2e/config.toml" - POETRY_VIRTUALENVS_CREATE: ${{ vars.POETRY_VIRTUALENVS_CREATE }} uses: ansys/actions/tests-pytest@v10 with: python-version: ${{ env.MAIN_PYTHON_VERSION }} From 62d1ba8516229800741e8806767d9bcaa39fba38 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Tue, 15 Jul 2025 10:39:57 +0100 Subject: [PATCH 37/38] removed dependency so it starts --- .github/workflows/ci_cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 31eed623..b338c950 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -158,7 +158,7 @@ jobs: tests-e2e: name: E2E Tests runs-on: ubuntu-22.04 - needs: [ tests ] +# needs: [ tests ] container: image: ${{ format('ghcr.io/ansys/optislang:{0}-jammy', '25.2.0') }} credentials: From d7951f5fad2758d0057c51cdefc88868ee4b04e8 Mon Sep 17 00:00:00 2001 From: Philip Usher Date: Wed, 16 Jul 2025 09:24:34 +0100 Subject: [PATCH 38/38] update timeout --- .github/workflows/ci_cd.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index b338c950..e9af315e 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -158,7 +158,8 @@ jobs: tests-e2e: name: E2E Tests runs-on: ubuntu-22.04 -# needs: [ tests ] + timeout-minutes: 2160 + # needs: [ tests ] container: image: ${{ format('ghcr.io/ansys/optislang:{0}-jammy', '25.2.0') }} credentials: