From d1385dd761eacd1b8b4cafaafab2ac74c3ecc124 Mon Sep 17 00:00:00 2001 From: Jean Henry <126060567+ansjhenry@users.noreply.github.com> Date: Mon, 19 Feb 2024 17:53:42 +0100 Subject: [PATCH] test: Setup tests (#4) * Add a test project for the workflow * Activate the tests --- .github/workflows/ci_cd.yml | 15 +- scade-tests-pytest/action.yml | 14 +- tests/python/.gitignore | 32 ++ .../requirements/requirements_tests.txt | 2 + tests/python/setup.py | 12 + tests/python/src/test_package/__init__.py | 21 + tests/python/src/test_package/script.py | 45 +++ tests/python/tests/conftest.py | 90 +++++ tests/python/tests/resources/Model.etp | 364 ++++++++++++++++++ tests/python/tests/resources/P.xscade | 130 +++++++ tests/python/tests/test_script.py | 54 +++ 11 files changed, 768 insertions(+), 11 deletions(-) create mode 100644 tests/python/.gitignore create mode 100644 tests/python/requirements/requirements_tests.txt create mode 100644 tests/python/setup.py create mode 100644 tests/python/src/test_package/__init__.py create mode 100644 tests/python/src/test_package/script.py create mode 100644 tests/python/tests/conftest.py create mode 100644 tests/python/tests/resources/Model.etp create mode 100644 tests/python/tests/resources/P.xscade create mode 100644 tests/python/tests/test_script.py diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 2b61e36..a873334 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -137,7 +137,7 @@ jobs: runs-on: [self-hosted, 'SCADE'] strategy: matrix: - # scade-version: ['19.2', '19.4', '21.1', '21.2'] + # scade-version: ['23.1', '23.2'] scade-version: ['23.1'] fail-fast: false steps: @@ -164,12 +164,13 @@ jobs: target-dir: '.venvs' target-name: ${{ steps.get-scade-python.outputs.python-name }} - # no test application for now - # - name: Execute tests - # uses: ./scade-tests-pytest - # with: - # python-dir: ${{ steps.create-scade-venv.outputs.scripts-dir }} - # checkout: false + - name: Execute tests + uses: ./scade-tests-pytest + with: + python-dir: ${{ steps.create-scade-venv.outputs.scripts-dir }} + library-dir: "tests/python" + pytest-postargs: "tests/python/tests -vv" + checkout: false doc-deploy-dev: name: "Deploy developers documentation" diff --git a/scade-tests-pytest/action.yml b/scade-tests-pytest/action.yml index d7949f6..c8ddeea 100644 --- a/scade-tests-pytest/action.yml +++ b/scade-tests-pytest/action.yml @@ -14,6 +14,12 @@ inputs: required: true # Optional inputs + library-dir: + description: > + Directory of the library to test. + default: '.' + required: false + pytest-markers: description: > Set of `pytest markers @@ -75,15 +81,15 @@ runs: - name: "Install Python library" shell: cmd run: | - %PYTHON_EXE% -m pip install . + %PYTHON_EXE% -m pip install ${{ inputs.library-dir }} - - name: "Check if requirements.txt file exists" + - name: "Check if requirements_tests.txt file exists" shell: cmd run: | :: Add the requirements - if exist requirements/requirements_tests.txt ( + if exist ${{ inputs.library-dir }}/requirements/requirements_tests.txt ( echo Install test dependencies from the requirements file - %PYTHON_EXE% -m pip install -r requirements/requirements_tests.txt + %PYTHON_EXE% -m pip install -r ${{ inputs.library-dir }}/requirements/requirements_tests.txt ) # - name: "Install test dependencies from pyproject.toml" diff --git a/tests/python/.gitignore b/tests/python/.gitignore new file mode 100644 index 0000000..c024220 --- /dev/null +++ b/tests/python/.gitignore @@ -0,0 +1,32 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST +TestResults +*.pyproj +*.sln +*.vsw diff --git a/tests/python/requirements/requirements_tests.txt b/tests/python/requirements/requirements_tests.txt new file mode 100644 index 0000000..71b21e3 --- /dev/null +++ b/tests/python/requirements/requirements_tests.txt @@ -0,0 +1,2 @@ +pytest==7.1.2 +pytest-cov==3.0.0 diff --git a/tests/python/setup.py b/tests/python/setup.py new file mode 100644 index 0000000..f7196ab --- /dev/null +++ b/tests/python/setup.py @@ -0,0 +1,12 @@ +from setuptools import find_packages, setup + +setup( + name="test_package", + version="0.1.dev0", + url="https://github.com/test-package-for-scade-actions.git", + author="ESEG", + author_email="test@unknown.com", + description="Test purpose", + packages=find_packages(where="./src"), + package_dir={"": "src"}, +) diff --git a/tests/python/src/test_package/__init__.py b/tests/python/src/test_package/__init__.py new file mode 100644 index 0000000..3bc3c8e --- /dev/null +++ b/tests/python/src/test_package/__init__.py @@ -0,0 +1,21 @@ +# Copyright (C) 2023 - 2024 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/python/src/test_package/script.py b/tests/python/src/test_package/script.py new file mode 100644 index 0000000..458e59d --- /dev/null +++ b/tests/python/src/test_package/script.py @@ -0,0 +1,45 @@ +# Copyright (C) 2023 - 2024 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. + +""" +Simple script to verify the correct execution of the actions. +""" + +from pathlib import Path + +from scade import output +from scade.model.project.stdproject import get_roots as get_projects +from scade.model.suite import get_roots as get_sessions + + +def get_project_names(projects): + return [Path(_.pathname).name for _ in projects] + + +def get_operator_paths(model): + return [_.get_full_path() for _ in model.all_operators] + + +if __name__ == "__main__": + output(str(get_project_names(get_projects())) + "\n") + # assume one and only one SCADE project + output(str(get_operator_paths(get_sessions()[0].model)) + "\n") diff --git a/tests/python/tests/conftest.py b/tests/python/tests/conftest.py new file mode 100644 index 0000000..95db65f --- /dev/null +++ b/tests/python/tests/conftest.py @@ -0,0 +1,90 @@ +# Copyright (C) 2023 - 2024 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +"""Unit tests fixtures.""" + +import os +import re +import sys +from inspect import getsourcefile +from pathlib import Path + +# import pytest + +# set sys.path from the python interpreter location (/SCADE/contrib/Python3xx) +# note: these tests are executed in the context of a virtual environment +# on top of a SCADE's Python distribution + +for line in (Path(sys.executable).parent.parent / "pyvenv.cfg").open("r"): + m = re.match(r"^home\s*=\s*(.*)$", line) + if m: + contrib = Path(m.groups()[0]).parent + break + +assert contrib +base = contrib.parent / "SCADE" +bin = base / "bin" +assert bin.exists() +sys.path.append(str(bin)) +lib = base / "APIs" / "Python" / "lib" +assert lib.exists() +sys.path.append(str(lib)) + + +# can be imported since sys.path is updated +# isort: split +# activate the SCADE Python APIs by importing scade_env +import scade_env # noqa: E402, F401 + +# must be imported after scade_env +# isort: split +import scade # noqa: E402 +import scade.model.suite as suite # noqa: E402 + + +def get_resources_dir() -> Path: + """Return the directory ./resources relative to this file's directory.""" + script_path = Path(os.path.abspath(getsourcefile(lambda: 0))) + return script_path.parent + + +def load_session(pathname: Path): + """ + Load a Scade model in a separate environment. + + Note: The model can have unresolved references since the libraries + are not loaded. + """ + session = suite.Session() + session.load2(str(pathname)) + assert session.model + return session + + +def load_project(pathname: Path): + """ + Load a Scade project in a separate environment. + + Note: Undocumented API. + """ + project_ = scade.load_project(str(pathname)) + return project_ diff --git a/tests/python/tests/resources/Model.etp b/tests/python/tests/resources/Model.etp new file mode 100644 index 0000000..50af156 --- /dev/null +++ b/tests/python/tests/resources/Model.etp @@ -0,0 +1,364 @@ + + + + + SC + + + SCADE65 + + + $(Configuration) + 14 + + + /nologo /ML /O2 + 14 + + + C QUAL663 + 14 + + + char + float32 + float64 + int8 + int16 + int32 + int64 + uint8 + uint16 + uint32 + uint64 + size + 14 + + + $(TargetDir)\user_macros.h + 14 + + + false + 14 + + + win64 + 14 + + + Code Generator + 14 + 23 + 44 + 57 + + + $(Configuration) + 23 + + + /nologo /ML /O2 + 23 + + + C QUAL663 + 23 + + + char + float32 + float64 + int8 + int16 + int32 + int64 + uint8 + uint16 + uint32 + uint64 + size + 23 + + + true + 23 + + + true + 23 + + + true + 23 + + + Simulator + 23 + + + $(TargetDir)\user_macros.h + 23 + + + win64 + 23 + + + Reporter/ScadeReport.tcl + 34 + + + true + 34 + + + Flat + 34 + + + Reporter + 34 + 39 + 44 + 65 + + + rtf + 39 + + + Reporter/ScadeReport.tcl + 39 + + + true + 39 + + + Flat + 39 + + + $(Configuration) + 44 + + + /nologo /ML /O2 + 44 + + + C QUAL663 + 44 + + + char + float32 + float64 + int8 + int16 + int32 + int64 + uint8 + uint16 + uint32 + uint64 + size + 44 + + + $(TargetDir)\user_macros.h + 44 + + + true + 44 + + + + 44 + + + Simulator + 44 + + + win64 + 44 + + + $(SCADE)/scripts/MetricRule/DefaultMetrics.py + $(SCADE)/scripts/MetricRule/DefaultRules.py + + + Metrics and Rules Checker + 54 + + + $(Configuration) + 57 + + + /nologo /ML /O2 + 57 + + + C QUAL663 + 57 + + + char + float32 + float64 + int8 + int16 + int32 + int64 + uint8 + uint16 + uint32 + uint64 + size + 57 + + + $(TargetDir)\user_macros.h + 57 + + + T&S Optimizer + 57 + + + Timing and Stack Verifiers + 57 + + + rtf + 65 + + + Reporter/ScadeQualifiedReport.tcl + 65 + + + true + 65 + + + Flat + 65 + + + true + 65 + + + true + 65 + + + true + 65 + + + Model.xscade + + + Model.err + + + $(SCADE)/lib/DefaultAty.aty + + + true + + + <title> + + + <subtitle> + + + <description> + + + <authors> + + + <company> + + + <date> + + + <index> + + + <reference> + + + Timing and Stack Analysis Tools + 14 + 23 + 34 + 39 + 44 + 54 + 57 + 65 + + + DiffAnalyzer + 14 + 23 + 34 + 39 + 44 + 54 + 57 + 65 + + + Synchronization + 14 + 23 + 34 + 39 + 44 + 54 + 57 + 65 + + + Import/Export + 14 + 23 + 34 + 39 + 44 + 54 + 57 + 65 + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/python/tests/resources/P.xscade b/tests/python/tests/resources/P.xscade new file mode 100644 index 0000000..fb969fe --- /dev/null +++ b/tests/python/tests/resources/P.xscade @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/python/tests/test_script.py b/tests/python/tests/test_script.py new file mode 100644 index 0000000..dad14ed --- /dev/null +++ b/tests/python/tests/test_script.py @@ -0,0 +1,54 @@ +# Copyright (C) 2023 - 2024 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. + +""" +Test suite for script.py. + +Test strategy: + +* Verify the returned values for a simple Scade model. +""" + +import pytest +from conftest import get_resources_dir, load_project, load_session +from test_package import script + + +@pytest.fixture(scope="session") +def roots(): + """Unique instance of the test model Model.""" + path = get_resources_dir() / "resources" / "Model.etp" + project = load_project(path) + session = load_session(path) + return project, session + + +def test_get_project_names(roots): + project, _ = roots + names = script.get_project_names([project]) + assert names == ["Model.etp"] + + +def test_get_operator_paths(roots): + _, session = roots + paths = script.get_operator_paths(session.model) + assert paths == ["P::Root/"]