From 813a9cf541cf558b4c570fbd3fa1439b194849de Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Thu, 9 Dec 2021 17:12:37 -0700 Subject: [PATCH 01/62] initial work --- doc/source/documentation_style/index.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/source/documentation_style/index.rst b/doc/source/documentation_style/index.rst index e275b380e..282ed2d20 100644 --- a/doc/source/documentation_style/index.rst +++ b/doc/source/documentation_style/index.rst @@ -29,6 +29,8 @@ The documentation for a PyAnsys library should contain: * User guide for the library. * Link to this developer's guide. +Finally the documentation should be public and hosted via gh-pages, either as a branch named ``gh-pages`` within the library repository, or within a ``gh-pages`` branch within ``-docs``. See :ref:`doc_deployment` for more details. + .. toctree:: :hidden: :maxdepth: 3 @@ -36,3 +38,4 @@ The documentation for a PyAnsys library should contain: docstrings class_documentation coding_style + deployment From 5d62fb2dff16a40ab6492835031abae7632731d9 Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Thu, 9 Dec 2021 17:12:46 -0700 Subject: [PATCH 02/62] add file --- doc/source/documentation_style/deployment.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 doc/source/documentation_style/deployment.rst diff --git a/doc/source/documentation_style/deployment.rst b/doc/source/documentation_style/deployment.rst new file mode 100644 index 000000000..be0014b0e --- /dev/null +++ b/doc/source/documentation_style/deployment.rst @@ -0,0 +1,12 @@ +.. _api_documentation: + + +Documentation Deployment +------------------------ +Documentation for the PyAnsys project is hosted via `GitHub Pages `_. Given the open-source nature of the project, documentation build by each PyAnsys library or project should be public and editable by users and the community at large. + +After following the documentation build strategy contained within both +the `pyansys/template `_ and +`pyansys-sphinx-theme +`_ you will end up +with html documentation files contained within `doc/build/html`. From 216b4f52d0f96d0810fc47329fdf1efa19cd1cbc Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Thu, 30 Dec 2021 14:17:46 -0700 Subject: [PATCH 03/62] add in testing guide --- doc/source/overview/dev_practices.rst | 111 +++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index d6eb658dc..eb4738a23 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -194,4 +194,113 @@ should not wait until a minor release. These are the steps for a patch release: Testing ------- - +Unit testing is critical for the sucessful continious integration and testing of +any program or libraries belonging to the PyAnsys project are no exception. + +There are generally two types of libraries part of the PyAnsys project: those that +interface or wrap functionality of a different product, service, or application, or +those that provide functionality. Both types of libraries should be tested, but the +tests written will depend on purpose of the library. For example, a library that is +wrapping a gRPC interface would include tests of the gRPC methods exposed by the proto +files and wrapped by your Python library. For example, if testing the gRPC method ``GetNode``, your test would test +the wrapped method (for example, ``get_node``). For example the ``get_node`` method +might be implemented as: + +.. code:: + + Proto interface here. + + +.. code:: python + +from ansys.product.service.v0 import service_pb2 + + def get_node(self, index): + """Return the coordinates of a node for a given index. + + Parameters + ---------- + index : int + Index of the node. + + Returns + ------- + tuple + Coordinates of the node. + + Examples + -------- + >>> from ansys.product.service import Service + >>> srv = Service() + >>> srv.create_node(1, 4.5, 9.0, 3.2) + >>> node = srv.get_node(1) + >>> node + (4.5, 9.0, 3.2) + + """ + resp = service_pb2.GetNode(index=index) + return resp.x, resp.y, resp.z + +Your test would look like: + +.. code:: + + def test_get_node(srv): + srv.clear() + + node_index = 1 + node_coord = 0, 10, 20 + srv.create_node(node_index, node_coord*) + assert srv.get_node(node_index) == node_coord + +The goal of the unit test should be to test the wrapping of the interface rather +than the product or service itself, which would be instead tested at the product or +service level. In the case of the ``GetNode``, this method should have already been +tested when designing and developing the service. + + +Remote Method Invocation Testing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In the case of a Remote Method Invocation (RMI)-like method, it is only necessary +to test the method with a basic case and potentially with any edge cases. + +RMI Service Definition: + +.. code:: + + message SendCommand() + + +Python Wrapping + +.. code:: + + def send_command(command): + """Run a command on the server. + + Parameters + ---------- + command : str + Command to run on the remote server. Should be in the form of + + + + + +Files Layout +~~~~~~~~~~~~ +PyAnsys libraries should use ``unittest`` or ``pytest`` libraries to run individual +unit tests contained within a ``tests`` directory in the root of the project. The +testing specific files of your project should at a minimum include: + +.. code:: + + requirements_tests.py + tests/ + test_.py + conftest.py + +**Requirements File** +The requirements file contains a list of all the libraries that must be installed to +run ``pytest``. No assumption should be made regarding the state of the virtual + From f8afaec27a52df156f9d6aad84f7c0c2dde9ad51 Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Thu, 3 Feb 2022 02:51:43 -0700 Subject: [PATCH 04/62] add CI sections --- .../repo_directory_structure.rst | 2 + doc/source/overview/dev_practices.rst | 303 ++++++++++++++++-- 2 files changed, 283 insertions(+), 22 deletions(-) diff --git a/doc/source/library_description/repo_directory_structure.rst b/doc/source/library_description/repo_directory_structure.rst index 1da6fcb45..21979929e 100644 --- a/doc/source/library_description/repo_directory_structure.rst +++ b/doc/source/library_description/repo_directory_structure.rst @@ -1,3 +1,5 @@ +.. _repo_dir_struct: + Repository Directory Structure ------------------------------ The source for a PyAnsys library is hosted in an individual diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index eb4738a23..7b5bdcd6f 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -11,7 +11,7 @@ contributing directly to PyAnsys libraries. General Development Procedures ------------------------------ -To submit new code to a PyAnsys, first `fork `_ +To submit new code to a PyAnsys, first `fork `_ the repository (for example `PyMAPDL `_) and then clone the forked repository to your local environment. Next, create a new branch based on the `Branch Naming Conventions Section <#branch-naming-conventions>`__ in @@ -75,7 +75,7 @@ See :ref:`license_file` for more details. Branching Model --------------- This project has a branching model that enables rapid development of -features without sacrificing stability and closely follows the +features without sacrificing stability and closely follows the `Trunk Based Development `_ approach. Descriptions follow for the main features of the branching model. @@ -146,7 +146,7 @@ Procedures follow for major and minor releases. #. When the branch is deemed as stable for public release, the PR is merged to `main` branch, which is then tagged with a `MAJOR.MINOR.0` release. The release branch will not be deleted. - + Tag the release with: .. code:: @@ -197,23 +197,45 @@ Testing Unit testing is critical for the sucessful continious integration and testing of any program or libraries belonging to the PyAnsys project are no exception. -There are generally two types of libraries part of the PyAnsys project: those that -interface or wrap functionality of a different product, service, or application, or -those that provide functionality. Both types of libraries should be tested, but the -tests written will depend on purpose of the library. For example, a library that is -wrapping a gRPC interface would include tests of the gRPC methods exposed by the proto -files and wrapped by your Python library. For example, if testing the gRPC method ``GetNode``, your test would test -the wrapped method (for example, ``get_node``). For example the ``get_node`` method -might be implemented as: +There are generally two types of libraries part of the PyAnsys project: those +that interface or wrap functionality of a different Ansys product, service, or +application, or tools those that provide functionality. Both types of libraries +should be tested, but the tests written will depend on purpose of the library. +For example, a library that is wrapping a gRPC interface would include tests of +the gRPC methods exposed by the proto files and wrapped by the Python library, but would not be expected to test the functionality of the server. + +For example, if testing the gRPC method ``GetNode``: .. code:: - Proto interface here. + message Node + { + int32 id = 1; + double x = 2; + double y = 3; + double z = 4; + } + + message NodeRequest { + int32 num = 1; + } + + message NodeResponse { + Node node = 1; + } + + service SomeService{ + rpc GetNode(NodeRequest) returns (NodeResponse); + // other methods + } + +Then youyour unit test would test the wrapped python function (for example, +``get_node``). For example the ``get_node`` method might be implemented as: .. code:: python -from ansys.product.service.v0 import service_pb2 + from ansys.product.service.v0 import service_pb2 def get_node(self, index): """Return the coordinates of a node for a given index. @@ -230,8 +252,8 @@ from ansys.product.service.v0 import service_pb2 Examples -------- - >>> from ansys.product.service import Service - >>> srv = Service() + >>> from ansys.product.service import SomeService + >>> srv = SomeService() >>> srv.create_node(1, 4.5, 9.0, 3.2) >>> node = srv.get_node(1) >>> node @@ -241,7 +263,7 @@ from ansys.product.service.v0 import service_pb2 resp = service_pb2.GetNode(index=index) return resp.x, resp.y, resp.z -Your test would look like: +Your test would be implemented (within ``tests/test_nodes.py``): .. code:: @@ -254,9 +276,247 @@ Your test would look like: assert srv.get_node(node_index) == node_coord The goal of the unit test should be to test the wrapping of the interface rather -than the product or service itself, which would be instead tested at the product or -service level. In the case of the ``GetNode``, this method should have already been -tested when designing and developing the service. +than the product or service itself. In the case of the ``GetNode``, this method +should have already been tested when designing and developing the service. + + +Testing Framework +~~~~~~~~~~~~~~~~~ +For consistency, PyAnsys tools and libraries should use either the `unit test +`_ or `pytest `_ frameworks for unit testing. As detailed +in the :ref:`repo_dir_struct`, unit tests should be placed into the ``tests`` +directory in the of the root directory of the library:: + + tests/ + test_basic.py + test_advanced.py + +Furthermore, any testing dependencies requirements should be included when using ``setup.py`` within a ``requirements_tests.txt`` file that is installed via:: + +.. code:: + + pip install -r requirements_tests.txt + +Or included in ``pyproject.toml``. For example, when using the `filt +`_ build system:: + + [project.optional-dependencies] + test = [ + "pytest>=2.7.3", + "pytest-cov", + ] + +And then installed via:: + + pip install .[test] + +When using ``pytest``, test via:: + + pytest + +.. note:: + Note that it is preferable to cd into the testing directory and run unit + testing there as you will be testing the installed library (generally in + development mode ``pip install -e .``) rather than the source within the + uninstalled "local" source. This catches files that might be missed by the + installer, including any C extensions or additional internal packages. + + +Coverage +~~~~~~~~ +As Python is an interpreted language, developers of any Python library should +aim to have high coverage for their library as only syntax errors can be caught +during the almost trivial compile time. Coverage is defined as parts of the +executable and usable source that are tested by unit tests, and the coverage for +your library can be viewed using the ``pytest-cov`` library. For example:: + + $ pytest --cov numpydoc_validation + ============================= test session starts ============================== + platform linux -- Python 3.8.10, pytest-6.2.5, py-1.11.0, pluggy-1.0.0 + rootdir: /home/user/python/numpydoc_validation + plugins: cov-3.0.0 + collected 1 item + + tests/test_validate.py . [100%] + + ---------- coverage: platform linux, python 3.8.10-final-0 ----------- + Name Stmts Miss Cover + ------------------------------------------------------ + numpydoc_validation/__init__.py 2 0 100% + numpydoc_validation/_validate.py 69 0 100% + ------------------------------------------------------ + TOTAL 71 0 100% + +While 100% coverage is ideal, the law of diminishing returns often applies to +the coverage of a Python library, and it is often sufficient, to achieve 80-90% +coverage. For parts of your library that are difficult or impossible to test, +consider using ``# pragma: no cover`` at the end of method definition, branch, +or line to denote that part of the code cannot be reasonably tested. For +example, if part of your module performs a simple ``import`` test of +``matplotlib`` and raises an error when the library is not installed, it is not +reasonable to attempt to test this and assume full coverage: + +.. code:: python + + try: + import matplotlib + except ImportError: # pragma: no cover + raise ImportError("Please install matplotlib to use this feature") + +.. note:: + You should only avoid coverage of parts of your library where you cannot + reasonably test without an extensive testing suite or setup. Most methods + and classes, including edge cases, can be reasonable tested. Even parts of + your code that raise errors like ``TypeError`` or ``ValueError`` when users + input the wrong data type or value. + + +Unit Testing within CI/CD +~~~~~~~~~~~~~~~~~~~~~~~~~ +Effective CI/CD assumes that unit testing is developed during feature +development or bug fixes. However, given the limited scope of the local +development environment, it is often not possible to enforce testing on multiple +platforms, or even, unit testing in general. However, with the right automated +CI/CD, such testing can still occur and be enforced automatically. + +`GitHub Actions `_ is the preferred automated CI/CD platform +for running Python library unit tests for PyAnsys, and can be employed +immediately by closing the project `template `_. For a basic overview of those unfamiliar of +GitHub Actions, read: `missing link `_. + +**Sample Workflow** + +The following sections detail the usage of a simple GitHub workflow for a +PyAnsys library: + +**Setup** + +Include the name and when your job should be run at the top of the workflow ``.yml``:: + + name: Unit Testing + + on: + pull_request: + workflow_dispatch: + push: + tags: + - "*" + branches: + - main + +Take note that here we run the this workflow on all pull requests and on demand +with ``workflow_dispatch``, but limit it being run on commits to only tags and +on the ``main`` branch. This ensures that CI/CD is not run twice on every +commit for each PR, which may saturate available build or testing machines. + +**Job Description** + +PyAnsys Libraries should run on the currently supported versions of Python on both Windows and Linux (and ideally Mac OS). Therefore, it is necessary to also test on both Linux and Windows for these versions of Python. Use the ``matrix`` run strategy for the job with both the latest images of Windows and Linux:: + + jobs: + unit_tests: + name: Unit testing + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [windows-latest, ubuntu-latest] + python-version: ['3.7', '3.8', '3.9', '3.10'] + +**Running the Tests** + +Each virtual machine within GitHub actions starts in a fresh state with no +software or source installed or downloaded. Therefore it is necessary to both +clone the repository using the ``checkout`` action, as well as setup Python and +install the necessary testing dependencies. + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + +If you are using ``setup.py``, your installation step will be:: + + - name: Install the library + run: | + pip install . + pip install -r requirements_test.txt + +If you are using ``pyproject.toml`` with the ``flit`` build system, your +installation step will be:: + + - name: Install the library and dependencies + run: | + pip install flit + flit install + +Run the unit tests via ``pytest`` with:: + + - name: Test and show coverage + working-directory: tests + run: pytest --cov ansys.product.library + +.. note:: + Replace ``ansys.product.library`` with your library. This should match how it + would be imported within Python. For example, rather than + ``ansys-product-library`` use ``ansys.product.library``. + +Optionally, though highly recommended, upload your unit test coverage to +`codecov.io`_ with:: + + - uses: codecov/codecov-action@v2 + name: 'Upload coverage to Codecov' + +See the following section regarding the usage of `codecov.io`_. + + +Code Coverage Enforcement +~~~~~~~~~~~~~~~~~~~~~~~~~ +One way of enforcing unit test coverage with a project on GitHub is to use the +`codecov.io CI Bot`_ to enforce minimum patch (and optionally project) +coverage. As this application is already available to the `PyAnsys Organization +`_, simply add the following to the root directory +of your repository: + +**/codecov.yml** + +:: + + comment: + layout: "diff" + behavior: default + + coverage: + status: + project: + default: + # basic + # target: 50% + threshold: 0% + # advanced + if_not_found: success + if_ci_failed: error + if_no_uploads: error + patch: + default: + # basic + target: 90% + if_not_found: success + if_ci_failed: error + if_no_uploads: error + +This requires that each PR has a patch coverage of 90%, meaning that 90% any source added to the repository (unless ignored) must be covered by unit tests. + +.. note:: + This is only a sample configuration. + +Test Driven Development +~~~~~~~~~~~~~~~~~~~~~~~ + + Remote Method Invocation Testing @@ -282,7 +542,7 @@ Python Wrapping ---------- command : str Command to run on the remote server. Should be in the form of - + @@ -290,7 +550,7 @@ Python Wrapping Files Layout ~~~~~~~~~~~~ PyAnsys libraries should use ``unittest`` or ``pytest`` libraries to run individual -unit tests contained within a ``tests`` directory in the root of the project. The +unit tests contained within a ``tests`` directory in the root of the project. The testing specific files of your project should at a minimum include: .. code:: @@ -303,4 +563,3 @@ testing specific files of your project should at a minimum include: **Requirements File** The requirements file contains a list of all the libraries that must be installed to run ``pytest``. No assumption should be made regarding the state of the virtual - From 76cb757e1aab3c81a69e8e4606b2627c0af21214 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:17:37 +0100 Subject: [PATCH 05/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 7b5bdcd6f..44fe4333e 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -285,7 +285,7 @@ Testing Framework For consistency, PyAnsys tools and libraries should use either the `unit test `_ or `pytest `_ frameworks for unit testing. As detailed in the :ref:`repo_dir_struct`, unit tests should be placed into the ``tests`` -directory in the of the root directory of the library:: +directory in the root directory of the library:: tests/ test_basic.py From 1639d5a5d79565a2b903f6d2a1088657f266cea5 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:19:07 +0100 Subject: [PATCH 06/62] Update doc/source/documentation_style/deployment.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/documentation_style/deployment.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/source/documentation_style/deployment.rst b/doc/source/documentation_style/deployment.rst index be0014b0e..20a2278b1 100644 --- a/doc/source/documentation_style/deployment.rst +++ b/doc/source/documentation_style/deployment.rst @@ -3,7 +3,9 @@ Documentation Deployment ------------------------ -Documentation for the PyAnsys project is hosted via `GitHub Pages `_. Given the open-source nature of the project, documentation build by each PyAnsys library or project should be public and editable by users and the community at large. +Documentation for the PyAnsys project is hosted via `GitHub Pages `_. +Given the open-source nature of the project, documentation built by each PyAnsys library or +project should be public and editable by users and the community at large. After following the documentation build strategy contained within both the `pyansys/template `_ and From f14b6a2f3a518038008552aeb8b50fbb521654d1 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:19:26 +0100 Subject: [PATCH 07/62] Update doc/source/documentation_style/deployment.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/documentation_style/deployment.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/documentation_style/deployment.rst b/doc/source/documentation_style/deployment.rst index 20a2278b1..ee071d59a 100644 --- a/doc/source/documentation_style/deployment.rst +++ b/doc/source/documentation_style/deployment.rst @@ -11,4 +11,4 @@ After following the documentation build strategy contained within both the `pyansys/template `_ and `pyansys-sphinx-theme `_ you will end up -with html documentation files contained within `doc/build/html`. +with html documentation files in ``doc/build/html``. From ffe06879f77d54eec7b6410b61c230d8efe32833 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:19:51 +0100 Subject: [PATCH 08/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 44fe4333e..5cfbebc8b 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -200,7 +200,7 @@ any program or libraries belonging to the PyAnsys project are no exception. There are generally two types of libraries part of the PyAnsys project: those that interface or wrap functionality of a different Ansys product, service, or application, or tools those that provide functionality. Both types of libraries -should be tested, but the tests written will depend on purpose of the library. +should be tested, but the tests written will depend on the purpose of the library. For example, a library that is wrapping a gRPC interface would include tests of the gRPC methods exposed by the proto files and wrapped by the Python library, but would not be expected to test the functionality of the server. From 35a6271efbfdbb0634361a049626bbf1525e0706 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:20:00 +0100 Subject: [PATCH 09/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 5cfbebc8b..30092a97d 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -202,7 +202,7 @@ that interface or wrap functionality of a different Ansys product, service, or application, or tools those that provide functionality. Both types of libraries should be tested, but the tests written will depend on the purpose of the library. For example, a library that is wrapping a gRPC interface would include tests of -the gRPC methods exposed by the proto files and wrapped by the Python library, but would not be expected to test the functionality of the server. +the gRPC methods exposed by the proto files and wrapped by the Python library. They would not be expected to test the functionality of the server. For example, if testing the gRPC method ``GetNode``: From 915963868b3620a08099c3ac141854833e58b4e3 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:20:10 +0100 Subject: [PATCH 10/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 30092a97d..29c4c1056 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -230,7 +230,7 @@ For example, if testing the gRPC method ``GetNode``: // other methods } -Then youyour unit test would test the wrapped python function (for example, +Then your unit test would test the wrapped python function (for example, ``get_node``). For example the ``get_node`` method might be implemented as: .. code:: python From 4125ee95f7cdf51b434ad8a4bea529483958da1c Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:20:46 +0100 Subject: [PATCH 11/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 29c4c1056..6ebcd6dd8 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -283,8 +283,8 @@ should have already been tested when designing and developing the service. Testing Framework ~~~~~~~~~~~~~~~~~ For consistency, PyAnsys tools and libraries should use either the `unit test -`_ or `pytest `_ frameworks for unit testing. As detailed -in the :ref:`repo_dir_struct`, unit tests should be placed into the ``tests`` +`_ or `pytest `_ frameworks for unit testing. As described +in :ref:`repo_dir_struct`, unit tests should be placed into the ``tests`` directory in the root directory of the library:: tests/ From 5572012d249ad8294c189c1829283c08964d15e8 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:23:03 +0100 Subject: [PATCH 12/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 6ebcd6dd8..5255f509e 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -438,7 +438,7 @@ install the necessary testing dependencies. with: python-version: ${{ matrix.python-version }} -If you are using ``setup.py``, your installation step will be:: +If you are using ``setup.py``, your installation step is:: - name: Install the library run: | From 3db01e853384d15d8fb6f408979169ced73953ae Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:23:14 +0100 Subject: [PATCH 13/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 5255f509e..de16fa0bd 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -446,7 +446,7 @@ If you are using ``setup.py``, your installation step is:: pip install -r requirements_test.txt If you are using ``pyproject.toml`` with the ``flit`` build system, your -installation step will be:: +installation step is:: - name: Install the library and dependencies run: | From 52f6c2855ff75a9e9c9da12e48d007ebb5c334d1 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:23:58 +0100 Subject: [PATCH 14/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index de16fa0bd..a44cbdb79 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -325,7 +325,7 @@ When using ``pytest``, test via:: Coverage ~~~~~~~~ As Python is an interpreted language, developers of any Python library should -aim to have high coverage for their library as only syntax errors can be caught +aim to have high coverage for their libraries as only syntax errors can be caught during the almost trivial compile time. Coverage is defined as parts of the executable and usable source that are tested by unit tests, and the coverage for your library can be viewed using the ``pytest-cov`` library. For example:: From fd7b191c85d784a75b981f5deb2853e64f36aff8 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:31:55 +0100 Subject: [PATCH 15/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index a44cbdb79..16dcca707 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -12,7 +12,7 @@ General Development Procedures ------------------------------ To submit new code to a PyAnsys, first `fork `_ -the repository (for example `PyMAPDL `_) +the repository (for example, `PyMAPDL `_) and then clone the forked repository to your local environment. Next, create a new branch based on the `Branch Naming Conventions Section <#branch-naming-conventions>`__ in your local repository. From e0b40399c2d296303e280161285e47e160eda6b2 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:32:42 +0100 Subject: [PATCH 16/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 16dcca707..386409873 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -195,7 +195,7 @@ should not wait until a minor release. These are the steps for a patch release: Testing ------- Unit testing is critical for the sucessful continious integration and testing of -any program or libraries belonging to the PyAnsys project are no exception. +any program or libraries belonging to the PyAnsys project. There are generally two types of libraries part of the PyAnsys project: those that interface or wrap functionality of a different Ansys product, service, or From 16353bfdfc5ec254c6d5f72c8409adbaacbf9761 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:33:28 +0100 Subject: [PATCH 17/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 386409873..a93ef0fe6 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -348,8 +348,8 @@ your library can be viewed using the ``pytest-cov`` library. For example:: TOTAL 71 0 100% While 100% coverage is ideal, the law of diminishing returns often applies to -the coverage of a Python library, and it is often sufficient, to achieve 80-90% -coverage. For parts of your library that are difficult or impossible to test, +the coverage of a Python library. Consequently, achieving 80-90% coverage is often sufficient. +For parts of your library that are difficult or impossible to test, consider using ``# pragma: no cover`` at the end of method definition, branch, or line to denote that part of the code cannot be reasonably tested. For example, if part of your module performs a simple ``import`` test of From e7614582866220773a20a15ade35663d8ddcbba5 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:33:46 +0100 Subject: [PATCH 18/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index a93ef0fe6..e00e9a50b 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -382,8 +382,7 @@ CI/CD, such testing can still occur and be enforced automatically. `GitHub Actions `_ is the preferred automated CI/CD platform for running Python library unit tests for PyAnsys, and can be employed immediately by closing the project `template `_. For a basic overview of those unfamiliar of -GitHub Actions, read: `missing link `_. +github.com/pyansys/template>`_. If you are unfamiliar with GitHub Actions, see: `missing link `_ for an overview. **Sample Workflow** From e96769b4bec28295f66d8b65d5627c7096bbd551 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:33:57 +0100 Subject: [PATCH 19/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index e00e9a50b..b5a113402 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -386,7 +386,7 @@ github.com/pyansys/template>`_. If you are unfamiliar with GitHub Actions, see: **Sample Workflow** -The following sections detail the usage of a simple GitHub workflow for a +The following sections describe the usage of a simple GitHub workflow for a PyAnsys library: **Setup** From 1ee57c797d14f2fe4f88b9f9947c6a70f8788b25 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:34:09 +0100 Subject: [PATCH 20/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index b5a113402..ce61bc3df 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -404,7 +404,7 @@ Include the name and when your job should be run at the top of the workflow ``.y branches: - main -Take note that here we run the this workflow on all pull requests and on demand +Take note that this workflow runs on all pull requests and on demand with ``workflow_dispatch``, but limit it being run on commits to only tags and on the ``main`` branch. This ensures that CI/CD is not run twice on every commit for each PR, which may saturate available build or testing machines. From a556806eacc2fe94034b7a7c7f621795c46e78a8 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:34:33 +0100 Subject: [PATCH 21/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index ce61bc3df..a7d80a47e 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -411,7 +411,7 @@ commit for each PR, which may saturate available build or testing machines. **Job Description** -PyAnsys Libraries should run on the currently supported versions of Python on both Windows and Linux (and ideally Mac OS). Therefore, it is necessary to also test on both Linux and Windows for these versions of Python. Use the ``matrix`` run strategy for the job with both the latest images of Windows and Linux:: +PyAnsys libraries should run on the currently supported versions of Python on both Windows and Linux (and ideally on Mac OS). Therefore, it is necessary to also test on both Linux and Windows for these versions of Python. Use the ``matrix`` run strategy for the job with both the latest images of Windows and Linux:: jobs: unit_tests: From 9ffd004676633ea5167ca0a1e7d91fd55b1d363f Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:35:09 +0100 Subject: [PATCH 22/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index a7d80a47e..99995ab2a 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -405,7 +405,7 @@ Include the name and when your job should be run at the top of the workflow ``.y - main Take note that this workflow runs on all pull requests and on demand -with ``workflow_dispatch``, but limit it being run on commits to only tags and +with ``workflow_dispatch``. On commits, this workflow runs only on tags and on the ``main`` branch. This ensures that CI/CD is not run twice on every commit for each PR, which may saturate available build or testing machines. From 92191629efeb0c8152d31351729b52847c50c76f Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:36:45 +0100 Subject: [PATCH 23/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 99995ab2a..87b97ad26 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -425,9 +425,7 @@ PyAnsys libraries should run on the currently supported versions of Python on bo **Running the Tests** Each virtual machine within GitHub actions starts in a fresh state with no -software or source installed or downloaded. Therefore it is necessary to both -clone the repository using the ``checkout`` action, as well as setup Python and -install the necessary testing dependencies. +software or source installed or downloaded. Therefore, you must clone the repository using the ``checkout`` action, set up Python, and install the necessary testing dependencies. steps: - uses: actions/checkout@v2 From a97ee4bed80c5ff3dfda33423ce05b0eb75fa6fa Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:37:33 +0100 Subject: [PATCH 24/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 87b97ad26..6cd00038d 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -457,7 +457,7 @@ Run the unit tests via ``pytest`` with:: run: pytest --cov ansys.product.library .. note:: - Replace ``ansys.product.library`` with your library. This should match how it + Replace ``ansys.product.library`` with your library name. This should match how it would be imported within Python. For example, rather than ``ansys-product-library`` use ``ansys.product.library``. From 320f7e80c6ac2c6de1d43ba19c0d9f2c9c691dd7 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:38:02 +0100 Subject: [PATCH 25/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 6cd00038d..07d1e1c88 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -505,7 +505,7 @@ of your repository: if_ci_failed: error if_no_uploads: error -This requires that each PR has a patch coverage of 90%, meaning that 90% any source added to the repository (unless ignored) must be covered by unit tests. +This requires that each PR has a patch coverage of 90%, meaning that 90% of any source added to the repository (unless ignored) must be covered by unit tests. .. note:: This is only a sample configuration. From 2efa8d5badb646afc86bb99461c027d6b812ce74 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:38:16 +0100 Subject: [PATCH 26/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 07d1e1c88..6fd24f442 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -548,7 +548,7 @@ Files Layout ~~~~~~~~~~~~ PyAnsys libraries should use ``unittest`` or ``pytest`` libraries to run individual unit tests contained within a ``tests`` directory in the root of the project. The -testing specific files of your project should at a minimum include: +specific test files for your project should at a minimum include: .. code:: From 704865edc283a9720a37869fc02df4f783c3056e Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:38:57 +0100 Subject: [PATCH 27/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 6fd24f442..4aefc6953 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -316,7 +316,7 @@ When using ``pytest``, test via:: .. note:: Note that it is preferable to cd into the testing directory and run unit - testing there as you will be testing the installed library (generally in + testing there because you will be testing the installed library (generally in development mode ``pip install -e .``) rather than the source within the uninstalled "local" source. This catches files that might be missed by the installer, including any C extensions or additional internal packages. From ff5d7d356c06626b44dd21b5e0c8943f71dcc7bc Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:39:12 +0100 Subject: [PATCH 28/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 4aefc6953..bb4e653ca 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -276,7 +276,7 @@ Your test would be implemented (within ``tests/test_nodes.py``): assert srv.get_node(node_index) == node_coord The goal of the unit test should be to test the wrapping of the interface rather -than the product or service itself. In the case of the ``GetNode``, this method +than the product or service itself. In the case of ``GetNode``, this method should have already been tested when designing and developing the service. From d4fa5054698839ccfee7f5df64220c8c7024cb1a Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:39:31 +0100 Subject: [PATCH 29/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index bb4e653ca..fb5718437 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -324,7 +324,7 @@ When using ``pytest``, test via:: Coverage ~~~~~~~~ -As Python is an interpreted language, developers of any Python library should +Given that Python is an interpreted language, developers of Python libraries should aim to have high coverage for their libraries as only syntax errors can be caught during the almost trivial compile time. Coverage is defined as parts of the executable and usable source that are tested by unit tests, and the coverage for From 650adfd289282d2a88c90fb9c8a6de7f3680b9da Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:40:02 +0100 Subject: [PATCH 30/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index fb5718437..478d3a91f 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -510,7 +510,7 @@ This requires that each PR has a patch coverage of 90%, meaning that 90% of any .. note:: This is only a sample configuration. -Test Driven Development +Test-Driven Development ~~~~~~~~~~~~~~~~~~~~~~~ From a60a67c5bf4239bdf8f24d3b6fa3734499a7c5d3 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 11:12:07 +0100 Subject: [PATCH 31/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 478d3a91f..d9dea48fb 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -361,7 +361,7 @@ reasonable to attempt to test this and assume full coverage: try: import matplotlib except ImportError: # pragma: no cover - raise ImportError("Please install matplotlib to use this feature") + raise ImportError("Install matplotlib to use this feature.") .. note:: You should only avoid coverage of parts of your library where you cannot From 98cd6b7e6dc5997db044bbf802fe5a648bcfd550 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 11:13:58 +0100 Subject: [PATCH 32/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index d9dea48fb..320a74fb0 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -350,7 +350,7 @@ your library can be viewed using the ``pytest-cov`` library. For example:: While 100% coverage is ideal, the law of diminishing returns often applies to the coverage of a Python library. Consequently, achieving 80-90% coverage is often sufficient. For parts of your library that are difficult or impossible to test, -consider using ``# pragma: no cover`` at the end of method definition, branch, +consider using ``# pragma: no cover`` at the end of the method definition, branch, or line to denote that part of the code cannot be reasonably tested. For example, if part of your module performs a simple ``import`` test of ``matplotlib`` and raises an error when the library is not installed, it is not From 312bd65ba13262935a19525b405a8206d684c567 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 11:14:14 +0100 Subject: [PATCH 33/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 320a74fb0..4d431c6f9 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -327,8 +327,7 @@ Coverage Given that Python is an interpreted language, developers of Python libraries should aim to have high coverage for their libraries as only syntax errors can be caught during the almost trivial compile time. Coverage is defined as parts of the -executable and usable source that are tested by unit tests, and the coverage for -your library can be viewed using the ``pytest-cov`` library. For example:: +executable and usable source that are tested by unit tests. You can use the ``pytest-cov`` library to view the coverage for your library. For example:: $ pytest --cov numpydoc_validation ============================= test session starts ============================== From 184a34bf2aae38c58d41d5a32ffc898800aaf0b9 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 11:14:31 +0100 Subject: [PATCH 34/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 4d431c6f9..d981df19a 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -315,7 +315,7 @@ When using ``pytest``, test via:: pytest .. note:: - Note that it is preferable to cd into the testing directory and run unit + We recommend that you use ``cd`` to change to the ``testing`` directory and run unit testing there because you will be testing the installed library (generally in development mode ``pip install -e .``) rather than the source within the uninstalled "local" source. This catches files that might be missed by the From 0c887fb71321c707604abe23dd1109b2bf80df5f Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 11:14:55 +0100 Subject: [PATCH 35/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index d981df19a..e32ee4581 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -291,7 +291,7 @@ directory in the root directory of the library:: test_basic.py test_advanced.py -Furthermore, any testing dependencies requirements should be included when using ``setup.py`` within a ``requirements_tests.txt`` file that is installed via:: +Furthermore, any requirements for testing dependencies should be included when using ``setup.py`` within a ``requirements_tests.txt`` file that is installed via:: .. code:: From 04888ef0aa966b38aedb3566546b931dd77fbfa3 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 11:19:18 +0100 Subject: [PATCH 36/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index e32ee4581..d330b3d06 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -297,7 +297,7 @@ Furthermore, any requirements for testing dependencies should be included when u pip install -r requirements_tests.txt -Or included in ``pyproject.toml``. For example, when using the `filt +An alternative is to include requirements for dependencie in the ``pyproject.toml`` file. For example, when using the `filt `_ build system:: [project.optional-dependencies] From e723f5a5cbe459e2e703aa01c40d0681352a3fa5 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 11:23:21 +0100 Subject: [PATCH 37/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index d330b3d06..56d0a7528 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -367,7 +367,7 @@ reasonable to attempt to test this and assume full coverage: reasonably test without an extensive testing suite or setup. Most methods and classes, including edge cases, can be reasonable tested. Even parts of your code that raise errors like ``TypeError`` or ``ValueError`` when users - input the wrong data type or value. + input the wrong data type or value can be reasonably tested. Unit Testing within CI/CD From 6427db3278c45c7c7d9110420c5c9c946ded0f36 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 11:24:09 +0100 Subject: [PATCH 38/62] Update doc/source/overview/dev_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 56d0a7528..dd8fe9e84 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -231,7 +231,7 @@ For example, if testing the gRPC method ``GetNode``: } Then your unit test would test the wrapped python function (for example, -``get_node``). For example the ``get_node`` method might be implemented as: +``get_node``). You might implement the ``get_node`` method with: .. code:: python From c2852319d933c2409d1669a7333e47cde85c4312 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Mon, 14 Feb 2022 11:31:39 +0100 Subject: [PATCH 39/62] Update doc/source/documentation_style/index.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/documentation_style/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/documentation_style/index.rst b/doc/source/documentation_style/index.rst index 0da5295b7..beea17987 100644 --- a/doc/source/documentation_style/index.rst +++ b/doc/source/documentation_style/index.rst @@ -29,7 +29,7 @@ The documentation for a PyAnsys library should contain: * Developer's guide for the library. * Link to this developer's guide. -Finally the documentation should be public and hosted via gh-pages, either as a branch named ``gh-pages`` within the library repository, or within a ``gh-pages`` branch within ``-docs``. See :ref:`doc_deployment` for more details. +Finally the documentation should be public and hosted via gh-pages, either as a branch named ``gh-pages`` within the library repository or within a ``gh-pages`` branch within ``-docs``. For more information, see :ref:`doc_deployment`. .. toctree:: :hidden: From 90ce17143ece3343e0af3470f2485f76feb824ce Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Mon, 14 Feb 2022 12:31:29 +0100 Subject: [PATCH 40/62] Add poetry dependencies group for test. --- doc/source/overview/dev_practices.rst | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 99995ab2a..dfd94faf8 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -197,10 +197,10 @@ Testing Unit testing is critical for the sucessful continious integration and testing of any program or libraries belonging to the PyAnsys project. -There are generally two types of libraries part of the PyAnsys project: those -that interface or wrap functionality of a different Ansys product, service, or -application, or tools those that provide functionality. Both types of libraries -should be tested, but the tests written will depend on the purpose of the library. +There are generally two types of libraries part of the PyAnsys project: +* those that interface or wrap functionality of a different Ansys product, service, or application +* tools those that provide functionality +Both types of libraries should be tested, but the tests written will depend on the purpose of the library. For example, a library that is wrapping a gRPC interface would include tests of the gRPC methods exposed by the proto files and wrapped by the Python library. They would not be expected to test the functionality of the server. @@ -263,7 +263,7 @@ Then your unit test would test the wrapped python function (for example, resp = service_pb2.GetNode(index=index) return resp.x, resp.y, resp.z -Your test would be implemented (within ``tests/test_nodes.py``): +Your test would be implemented within ``tests/test_nodes.py``: .. code:: @@ -297,14 +297,12 @@ Furthermore, any testing dependencies requirements should be included when using pip install -r requirements_tests.txt -Or included in ``pyproject.toml``. For example, when using the `filt -`_ build system:: +Or included in ``pyproject.toml``. For example, when using the `poetry +`_ build system:: - [project.optional-dependencies] - test = [ - "pytest>=2.7.3", - "pytest-cov", - ] + [tool.poetry.group.test.dependencies] + pytest>="2.7.3" + pytest-cov = "*" And then installed via:: @@ -391,7 +389,7 @@ PyAnsys library: **Setup** -Include the name and when your job should be run at the top of the workflow ``.yml``:: +Include the job name when it should be run at the top of the workflow ``.yml``:: name: Unit Testing From cbc568d4c6cb2d48e576ddd76b1762b781243b7a Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Mon, 14 Feb 2022 14:36:32 +0100 Subject: [PATCH 41/62] Add link to poetry. --- doc/source/overview/dev_practices.rst | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 6e593ced0..73838806d 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -297,13 +297,8 @@ Furthermore, any requirements for testing dependencies should be included when u pip install -r requirements_tests.txt -<<<<<<< HEAD -Or included in ``pyproject.toml``. For example, when using the `poetry +An alternative is to include requirements for dependencie in the ``pyproject.toml`` file. For example, when using the `poetry `_ build system:: -======= -An alternative is to include requirements for dependencie in the ``pyproject.toml`` file. For example, when using the `filt -`_ build system:: ->>>>>>> c2852319d933c2409d1669a7333e47cde85c4312 [tool.poetry.group.test.dependencies] pytest>="2.7.3" From 9d14bd0303d75c403ba868d2235f6e57d94635a6 Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Mon, 14 Feb 2022 14:44:41 +0100 Subject: [PATCH 42/62] Coding style is not available. --- doc/source/documentation_style/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/source/documentation_style/index.rst b/doc/source/documentation_style/index.rst index beea17987..2b29f4859 100644 --- a/doc/source/documentation_style/index.rst +++ b/doc/source/documentation_style/index.rst @@ -37,5 +37,4 @@ Finally the documentation should be public and hosted via gh-pages, either as a docstrings class_documentation - coding_style deployment From 69ff8d996801eccba37e034331e7dbd72fec4ffb Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Mon, 14 Feb 2022 15:14:29 +0100 Subject: [PATCH 43/62] Fix conflict of the deployment and docstring main hypertext. --- doc/source/documentation_style/deployment.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/documentation_style/deployment.rst b/doc/source/documentation_style/deployment.rst index ee071d59a..1fdf0372c 100644 --- a/doc/source/documentation_style/deployment.rst +++ b/doc/source/documentation_style/deployment.rst @@ -1,4 +1,4 @@ -.. _api_documentation: +.. _documentation_deployment: Documentation Deployment From 02727b959be17c6b3b277925c2799e4cce4bc0bb Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Mon, 14 Feb 2022 15:17:46 +0100 Subject: [PATCH 44/62] Remove unexpected indentation. --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 73838806d..f27c77c4c 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -430,7 +430,7 @@ software or source installed or downloaded. Therefore, you must clone the reposi - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v1 with: - python-version: ${{ matrix.python-version }} + python-version: ${{ matrix.python-version }} If you are using ``setup.py``, your installation step is:: From 06a9d1b8f8b38c433c3801eae5044d990e683568 Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Mon, 14 Feb 2022 16:57:59 +0100 Subject: [PATCH 45/62] Improve code sample rendering. --- doc/source/overview/dev_practices.rst | 65 ++++++++++++++++----------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index f27c77c4c..1e7f26014 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -265,7 +265,7 @@ Then your unit test would test the wrapped python function (for example, Your test would be implemented within ``tests/test_nodes.py``: -.. code:: +.. code:: python def test_get_node(srv): srv.clear() @@ -424,34 +424,46 @@ PyAnsys libraries should run on the currently supported versions of Python on bo Each virtual machine within GitHub actions starts in a fresh state with no software or source installed or downloaded. Therefore, you must clone the repository using the ``checkout`` action, set up Python, and install the necessary testing dependencies. - steps: - - uses: actions/checkout@v2 +.. code:: - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 - with: + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: python-version: ${{ matrix.python-version }} -If you are using ``setup.py``, your installation step is:: - - name: Install the library - run: | - pip install . - pip install -r requirements_test.txt +If you are using ``setup.py``, your installation step is: + + +.. code:: yaml + + - name: Install the library + run: | + pip install . + pip install -r requirements_test.txt + + +If you are using ``pyproject.toml`` with the ``poetry`` build system, your +installation step is: -If you are using ``pyproject.toml`` with the ``flit`` build system, your -installation step is:: +.. code:: yaml - - name: Install the library and dependencies - run: | - pip install flit - flit install + - name: Install the library and dependencies + run: | + pip install poetry + poetry install -Run the unit tests via ``pytest`` with:: - - name: Test and show coverage - working-directory: tests - run: pytest --cov ansys.product.library +Run the unit tests via ``pytest`` with: + +.. code:: yaml + + - name: Test and show coverage + working-directory: tests + run: pytest --cov ansys.product.library + .. note:: Replace ``ansys.product.library`` with your library name. This should match how it @@ -461,8 +473,11 @@ Run the unit tests via ``pytest`` with:: Optionally, though highly recommended, upload your unit test coverage to `codecov.io`_ with:: - - uses: codecov/codecov-action@v2 - name: 'Upload coverage to Codecov' +.. code:: yaml + + - uses: codecov/codecov-action@v2 + name: 'Upload coverage to Codecov' + See the following section regarding the usage of `codecov.io`_. @@ -477,7 +492,7 @@ of your repository: **/codecov.yml** -:: +.. code:: yaml comment: layout: "diff" @@ -527,7 +542,7 @@ RMI Service Definition: Python Wrapping -.. code:: +.. code:: python def send_command(command): """Run a command on the server. From 2123f4af480c93b4e49beb0774a360e89fd114c6 Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Mon, 14 Feb 2022 17:04:37 +0100 Subject: [PATCH 46/62] Add link for codecov.io. --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 1e7f26014..92ee52ccc 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -471,7 +471,7 @@ Run the unit tests via ``pytest`` with: ``ansys-product-library`` use ``ansys.product.library``. Optionally, though highly recommended, upload your unit test coverage to -`codecov.io`_ with:: +`codecov.io `_ with:: .. code:: yaml From 0396cd3b31d2ebaa11a0161f36ec4f903f82f9bc Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Mon, 14 Feb 2022 17:11:28 +0100 Subject: [PATCH 47/62] Remove link for codecov.io CI Bot. --- doc/source/overview/dev_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/overview/dev_practices.rst b/doc/source/overview/dev_practices.rst index 92ee52ccc..5004501c2 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/overview/dev_practices.rst @@ -485,7 +485,7 @@ See the following section regarding the usage of `codecov.io`_. Code Coverage Enforcement ~~~~~~~~~~~~~~~~~~~~~~~~~ One way of enforcing unit test coverage with a project on GitHub is to use the -`codecov.io CI Bot`_ to enforce minimum patch (and optionally project) +**codecov.io CI Bot** to enforce minimum patch (and optionally project) coverage. As this application is already available to the `PyAnsys Organization `_, simply add the following to the root directory of your repository: From f11741a46c21e895bd09de08bd69fe555e160aa5 Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Mon, 14 Feb 2022 17:55:37 +0100 Subject: [PATCH 48/62] Add test_practices.rst. --- doc/source/guidelines/index.rst | 2 +- .../test_practices.rst} | 192 ------------------ 2 files changed, 1 insertion(+), 193 deletions(-) rename doc/source/{overview/dev_practices.rst => guidelines/test_practices.rst} (60%) diff --git a/doc/source/guidelines/index.rst b/doc/source/guidelines/index.rst index 7f171c51d..b3678fd26 100644 --- a/doc/source/guidelines/index.rst +++ b/doc/source/guidelines/index.rst @@ -21,4 +21,4 @@ Table of Contents logging service_abstraction PyMAPDL_WSL_Guide - + test_practices diff --git a/doc/source/overview/dev_practices.rst b/doc/source/guidelines/test_practices.rst similarity index 60% rename from doc/source/overview/dev_practices.rst rename to doc/source/guidelines/test_practices.rst index 5004501c2..4006518a8 100644 --- a/doc/source/overview/dev_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -1,195 +1,3 @@ -.. _development_practices: - -Development Practices -===================== - -This section explains how development is conducted in PyAnsys -repositories. Please follow the practices outlined here when -contributing directly to PyAnsys libraries. - - -General Development Procedures ------------------------------- - -To submit new code to a PyAnsys, first `fork `_ -the repository (for example, `PyMAPDL `_) -and then clone the forked repository to your local environment. Next, create a new branch based on the -`Branch Naming Conventions Section <#branch-naming-conventions>`__ in -your local repository. - -Next, add your new feature and commit it locally. Be sure to commit -often as it is often helpful to revert to past commits, especially if -your change is complex. Also, be sure to test often. See the `Testing -Section <#testing>`__ below for automating testing. - -When you are ready to submit your code, create a pull request by -following the steps in `Creating a New Pull Request <#creating-a-new-pull-request>`__. - -Be sure to review these topics: - -#. `Branching Section <#Branching Model>`__ -#. Testing standards. -#. Documentation standards. See :ref:`api_documentation`. -#. Code quality standards. See :ref:`coding_style`. - - -Guidelines -~~~~~~~~~~ - -Consider the following general coding paradigms when contributing: - -1. Follow the `Zen of Python `__. - As silly as the core Python developers are sometimes, there's much to - be gained by following the basic guidelines listed in PEP 20. - Without repeating them here, focus on making your additions - intuitive, novel, and helpful for users. - - When in doubt, ``import this``. - -2. **Document it**. Include a docstring for any function, method, or - class added. Follow the `numpydocs docstring - `_ - guidelines, and always provide an example of simple use cases for - new features. - -3. **Test it**. Because Python is an interpreted language, if it's not - tested, it's probably broken. At the minimum, include unit tests - for each new feature within the ``tests`` directory. Ensure that - each new method, class, or function has reasonable (>80%) coverage. - -Additionally, do not include any data sets for which a license -is not available or commercial use is prohibited. - -Licensing -~~~~~~~~~ - -All contributed code will be licensed under the MIT License found in -the repository. If you did not write the code yourself, it is your -responsibility to ensure that the existing license is compatible and -included in the contributed files. You must obtain permission from the -original author to relicense the code. - -See :ref:`license_file` for more details. - - -Branching Model ---------------- -This project has a branching model that enables rapid development of -features without sacrificing stability and closely follows the -`Trunk Based Development `_ approach. - -Descriptions follow for the main features of the branching model. - -- The `main` branch is the primary development branch. All features, - patches, and other branches should be merged here. While all pull - requests (PRs) should pass all applicable CI (Continuous Integration) - checks, this branch might be functionally unstable if changes have - introduced unintended side-effects or bugs that were not caught through - unit testing. -- There will be one or many `release/` branches based on minor - releases (for example, ``release/0.2``) that contain a stable version - of the code base that is also reflected on PyPI. Hotfixes from - `fix/` branches should be merged both to main and to these - branches. When creating a new patch release is necessary, these - release branches will have their ``__version__.py`` updated and be - tagged with a patched semantic version (for example, ``0.2.1``). This - triggers CI to push to PyPi and allow us to rapidly push hotfixes - for past versions without having to worry about untested features. -- When a minor release candidate is ready, a new ``release`` branch will - be created from ``main`` with the next incremented minor version - (for example, ``release/0.2``), This ``release`` branch will be thoroughly - tested. When deemed stable, it will be tagged with the version (``0.2.0`` - in this case) and merged with ``main`` if any changes were pushed to it. - Feature development then continues on ``main`` and any hotfixes will now - be merged with this release. Older release branches should not be deleted - so they can be patched as needed. - -.. _release_procedures: - -Release Procedures ------------------- - -Major and Minor -~~~~~~~~~~~~~~~ -Procedures follow for major and minor releases. - -#. Create a new branch from the `main` branch with name - ``release/MAJOR.MINOR`` (for example, ``release/0.2``). - -#. Locally run all tests as outlined in :ref:`testing` and ensure all - are passing. - -#. Locally test and build the documentation with link checking to make - sure no links are outdated. Be sure to run ``make clean`` to ensure no - results are cached. - - .. code:: - - cd doc - make clean # deletes the sphinx-gallery cache - make html -b linkcheck - -#. After building the documentation, open the local build and examine - the examples for any obvious issues. - -#. Update the version numbers in - ``ansys///_version.py`` and commit it. Push the - branch to GitHub and create a new PR for this release that merges - it to ``main``. Development to ``main`` should be limited while - effort is focused on the release. - -#. The community and Ansys developers must now functionally test the - new release. It is best to locally install this branch and use it in - production. Any bugs identified should have their hotfixes pushed to - this release branch. - -#. When the branch is deemed as stable for public release, the PR is merged - to `main` branch, which is then tagged with a `MAJOR.MINOR.0` release. - The release branch will not be deleted. - - Tag the release with: - - .. code:: - - git tag v - git push origin --tags - -#. Create a list of all changes for the release. It is often helpful - to see the differences from the last tag and the ``main`` branch - using `GitHub's compare feature`_ tool. Be sure to acknowledge new - contributors by their GitHub username and place mentions where - appropriate if a specific contributor is to be thanked for a new - feature. - -#. Place your release notes from the previous in the release section within the GitHub repository. See - `GitHub Releases`_ - -.. _GitHub Releases: https://docs.github.com/en/github/administering-a-repository/releasing-projects-on-github/managing-releases-in-a-repository -.. _GitHub's compare feature: https://github.com/pyansys/pymapdl/compare - - -Patch Release Steps -~~~~~~~~~~~~~~~~~~~ -Patch releases are for critical and important bug fixes that cannot or -should not wait until a minor release. These are the steps for a patch release: - -1. Push the necessary bug fixes to the applicable release branch. - This will generally be the latest release branch (`release/MAJOR.MINOR`). - -2. Update ``__version__.py`` with the next patch increment - (`MAJOR.MINOR.PATCH`), commit it, and open a PR to merge with the - release branch. This gives the developers and community - an opportunity to validate and approve the bug fix release. Any - additional hotfixes should be outside of this PR. - -3. When approved, merge with the release branch, but not `main` as - there is no reason to increment the version of the `main` branch. - Then, create a tag from the release branch with the applicable - version number (see above for the correct steps). - -4. If deemed necessary, add a release notes page. - - .. _testing: Testing From 4ad3469fccc0d19689453529d29425b30f0dc628 Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Tue, 15 Feb 2022 09:32:01 +0100 Subject: [PATCH 49/62] Fix the link. --- doc/source/documentation_style/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/documentation_style/index.rst b/doc/source/documentation_style/index.rst index 2b29f4859..124b434f9 100644 --- a/doc/source/documentation_style/index.rst +++ b/doc/source/documentation_style/index.rst @@ -29,7 +29,7 @@ The documentation for a PyAnsys library should contain: * Developer's guide for the library. * Link to this developer's guide. -Finally the documentation should be public and hosted via gh-pages, either as a branch named ``gh-pages`` within the library repository or within a ``gh-pages`` branch within ``-docs``. For more information, see :ref:`doc_deployment`. +Finally the documentation should be public and hosted via gh-pages, either as a branch named ``gh-pages`` within the library repository or within a ``gh-pages`` branch within ``-docs``. For more information, see :ref:`documentation_deployment`. .. toctree:: :hidden: From a0ba1149632751c4bff4bbe1b1fd8427443ab9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Mart=C3=ADnez?= <28702884+jorgepiloto@users.noreply.github.com> Date: Thu, 17 Feb 2022 17:56:51 +0100 Subject: [PATCH 50/62] Update doc/source/documentation_style/index.rst --- doc/source/documentation_style/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/documentation_style/index.rst b/doc/source/documentation_style/index.rst index 124b434f9..46511ce86 100644 --- a/doc/source/documentation_style/index.rst +++ b/doc/source/documentation_style/index.rst @@ -29,7 +29,7 @@ The documentation for a PyAnsys library should contain: * Developer's guide for the library. * Link to this developer's guide. -Finally the documentation should be public and hosted via gh-pages, either as a branch named ``gh-pages`` within the library repository or within a ``gh-pages`` branch within ``-docs``. For more information, see :ref:`documentation_deployment`. +Finally, the documentation should be public and hosted via gh-pages, either as a branch named ``gh-pages`` within the library repository or within a ``gh-pages`` branch within ``-docs``. For more information, see :ref:`documentation_deployment`. .. toctree:: :hidden: From 660591e155e0333ff1737f31e875245803ef88c9 Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Thu, 17 Feb 2022 18:47:37 +0100 Subject: [PATCH 51/62] line wrapping; general cleanup --- doc/source/documentation_style/index.rst | 5 +- doc/source/guidelines/test_practices.rst | 234 ++++++++++++++--------- 2 files changed, 143 insertions(+), 96 deletions(-) diff --git a/doc/source/documentation_style/index.rst b/doc/source/documentation_style/index.rst index 46511ce86..e3f77bb34 100644 --- a/doc/source/documentation_style/index.rst +++ b/doc/source/documentation_style/index.rst @@ -29,7 +29,10 @@ The documentation for a PyAnsys library should contain: * Developer's guide for the library. * Link to this developer's guide. -Finally, the documentation should be public and hosted via gh-pages, either as a branch named ``gh-pages`` within the library repository or within a ``gh-pages`` branch within ``-docs``. For more information, see :ref:`documentation_deployment`. +Finally, the documentation should be public and hosted via gh-pages, either as +a branch named ``gh-pages`` within the library repository or within a +``gh-pages`` branch within ``-docs``. For more information, +see :ref:`documentation_deployment`. .. toctree:: :hidden: diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index 4006518a8..ceecda35f 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -2,15 +2,35 @@ Testing ------- -Unit testing is critical for the sucessful continious integration and testing of -any program or libraries belonging to the PyAnsys project. +Unit and integration testing is critical for the successful continuous +integration and delivery of any program or libraries belonging to the PyAnsys +project. +`Test driven development`_ is the practice of writing unit tests before writing +production code. This has the benefit of knowing that each of the new lines of +code are working as soon as they're written. It's easier to track down problems +as only a small amount of code has been implemented since the execution of the +last test. Furthermore, all test cases do not have to be implemented at once +but rather gradually as the code evolves TDD has been created by Kent Beck in +the 1990's as part of the Extreme Programming software development process + +.. _Test driven development: https://en.wikipedia.org/wiki/Test-driven_development + +We recommend that you follow TDD when developing your PyAnsys project, and +this document contains examples and best practices to help you write them. + + +Sample gRPC Method Test +~~~~~~~~~~~~~~~~~~~~~~~ There are generally two types of libraries part of the PyAnsys project: -* those that interface or wrap functionality of a different Ansys product, service, or application +* those that interface or wrap functionality of a different Ansys product, + service, or application * tools those that provide functionality -Both types of libraries should be tested, but the tests written will depend on the purpose of the library. -For example, a library that is wrapping a gRPC interface would include tests of -the gRPC methods exposed by the proto files and wrapped by the Python library. They would not be expected to test the functionality of the server. +Both types of Python libraries should be tested, but the tests written will depend on +the purpose of the library. For example, a library that is wrapping a gRPC +interface would include tests of the gRPC methods exposed by the proto files +and wrapped by the Python library. They would not be expected to test the +functionality of the server. For example, if testing the gRPC method ``GetNode``: @@ -21,20 +41,20 @@ For example, if testing the gRPC method ``GetNode``: int32 id = 1; double x = 2; double y = 3; - double z = 4; + double z = 4; } message NodeRequest { - int32 num = 1; + int32 num = 1; } message NodeResponse { - Node node = 1; + Node node = 1; } service SomeService{ - rpc GetNode(NodeRequest) returns (NodeResponse); + rpc GetNode(NodeRequest) returns (NodeResponse); // other methods } @@ -83,30 +103,73 @@ Your test would be implemented within ``tests/test_nodes.py``: srv.create_node(node_index, node_coord*) assert srv.get_node(node_index) == node_coord -The goal of the unit test should be to test the wrapping of the interface rather -than the product or service itself. In the case of ``GetNode``, this method -should have already been tested when designing and developing the service. +The goal of the unit test should be to test the wrapping of the +interface rather than the product or service itself. In the case of +``GetNode``, this method should have already been tested when designing and +developing the service. + + +Remote Method Invocation Testing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In the case of a Remote Method Invocation (RMI)-like method, it is only necessary +to test the method with a basic case and potentially with any edge cases. + +RMI Service Definition: + +.. code:: + + message SendCommand() + + +Python wrapping: + +.. code:: python + + def send_command(command): + """Run a command on the server. + + Parameters + ---------- + command : str + Command to run on the remote server. + +Example test: + +.. code:: python + + def test_send_command(srv): + output = srv.send_command("CREATE,1") + assert "Created 1" in output + +Note that this test only validates the command ``"CREATE,1"`` has been +received, executed, and sent back to the client. It does not validate all +commands, but nor is it necessary to do this unless there are edge cases +(e.g. characters that cannot be streamed or dealing with long running +commands). Testing Framework ~~~~~~~~~~~~~~~~~ -For consistency, PyAnsys tools and libraries should use either the `unit test -`_ or `pytest `_ frameworks for unit testing. As described -in :ref:`repo_dir_struct`, unit tests should be placed into the ``tests`` +For consistency, PyAnsys tools and libraries should use either the `unittest +`_ or `pytest +`_ frameworks for unit testing. As described in +:ref:`repo_dir_struct`, unit tests should be placed into the ``tests`` directory in the root directory of the library:: tests/ test_basic.py test_advanced.py -Furthermore, any requirements for testing dependencies should be included when using ``setup.py`` within a ``requirements_tests.txt`` file that is installed via:: +Furthermore, any requirements for testing dependencies should be included when +using ``setup.py`` within a ``requirements_tests.txt`` file that is installed +via:: .. code:: pip install -r requirements_tests.txt -An alternative is to include requirements for dependencie in the ``pyproject.toml`` file. For example, when using the `poetry -`_ build system:: +An alternative is to include requirements for dependencies in the +``pyproject.toml`` file. For example, when using the `poetry`_ build system:: [tool.poetry.group.test.dependencies] pytest>="2.7.3" @@ -121,19 +184,22 @@ When using ``pytest``, test via:: pytest .. note:: - We recommend that you use ``cd`` to change to the ``testing`` directory and run unit - testing there because you will be testing the installed library (generally in - development mode ``pip install -e .``) rather than the source within the - uninstalled "local" source. This catches files that might be missed by the - installer, including any C extensions or additional internal packages. + We recommend that you place the source of your library within the ``src`` + direction rather than having your Python library source directly within the + repository root directory. This helps you avoid testing the source of the + repository and rather the installed package. This helps to catch errors + caused by files that might be missed by the installer, including any C + extensions or additional internal packages. Coverage ~~~~~~~~ -Given that Python is an interpreted language, developers of Python libraries should -aim to have high coverage for their libraries as only syntax errors can be caught -during the almost trivial compile time. Coverage is defined as parts of the -executable and usable source that are tested by unit tests. You can use the ``pytest-cov`` library to view the coverage for your library. For example:: +Given that Python is an interpreted language, developers of Python libraries +should aim to have high coverage for their libraries as only syntax errors can +be caught during the almost trivial compile time. Coverage is defined as parts +of the executable and usable source that are tested by unit tests. You can use +the `pytest-cov `_ library to view the +coverage for your library. For example:: $ pytest --cov numpydoc_validation ============================= test session starts ============================== @@ -153,13 +219,14 @@ executable and usable source that are tested by unit tests. You can use the ``py TOTAL 71 0 100% While 100% coverage is ideal, the law of diminishing returns often applies to -the coverage of a Python library. Consequently, achieving 80-90% coverage is often sufficient. -For parts of your library that are difficult or impossible to test, -consider using ``# pragma: no cover`` at the end of the method definition, branch, -or line to denote that part of the code cannot be reasonably tested. For -example, if part of your module performs a simple ``import`` test of -``matplotlib`` and raises an error when the library is not installed, it is not -reasonable to attempt to test this and assume full coverage: +the coverage of a Python library. Consequently, achieving 80-90% coverage is +often sufficient. For parts of your library that are difficult or impossible +to test, consider using ``# pragma: no cover`` at the end of the method +definition, branch, or line to denote that part of the code cannot be +reasonably tested. For example, if part of your module performs a simple +``import`` test of ``matplotlib`` and raises an error when the library is not +installed, it is not reasonable to attempt to test this and assume full +coverage: .. code:: python @@ -180,14 +247,16 @@ Unit Testing within CI/CD ~~~~~~~~~~~~~~~~~~~~~~~~~ Effective CI/CD assumes that unit testing is developed during feature development or bug fixes. However, given the limited scope of the local -development environment, it is often not possible to enforce testing on multiple -platforms, or even, unit testing in general. However, with the right automated -CI/CD, such testing can still occur and be enforced automatically. +development environment, it is often not possible to enforce testing on +multiple platforms, or even, unit testing in general. However, with the right +automated CI/CD, such testing can still occur and be enforced automatically. -`GitHub Actions `_ is the preferred automated CI/CD platform -for running Python library unit tests for PyAnsys, and can be employed -immediately by closing the project `template `_. If you are unfamiliar with GitHub Actions, see: `missing link `_ for an overview. +`GitHub Actions`_ is the preferred automated CI/CD platform for running Python +library unit tests for PyAnsys, and can be employed immediately by cloning the +project `template `_. If you are +unfamiliar with GitHub Actions, see `GitHub Actions`_ for an overview. + +.. _GitHub Actions: https://github.com/features/actions **Sample Workflow** @@ -209,14 +278,18 @@ Include the job name when it should be run at the top of the workflow ``.yml``:: branches: - main -Take note that this workflow runs on all pull requests and on demand -with ``workflow_dispatch``. On commits, this workflow runs only on tags and -on the ``main`` branch. This ensures that CI/CD is not run twice on every -commit for each PR, which may saturate available build or testing machines. +Take note that this workflow runs on all pull requests and on demand with +``workflow_dispatch``. On commits, this workflow runs only on tags and on the +``main`` branch. This ensures that CI/CD is not run twice on every commit for +each PR, which may saturate available build or testing machines. **Job Description** -PyAnsys libraries should run on the currently supported versions of Python on both Windows and Linux (and ideally on Mac OS). Therefore, it is necessary to also test on both Linux and Windows for these versions of Python. Use the ``matrix`` run strategy for the job with both the latest images of Windows and Linux:: +PyAnsys libraries should run on the currently supported versions of Python on +both Windows and Linux (and ideally on Mac OS). Therefore, it is necessary to +also test on both Linux and Windows for these versions of Python. Use the +``matrix`` run strategy for the job with both the latest images of Windows and +Linux:: jobs: unit_tests: @@ -230,7 +303,9 @@ PyAnsys libraries should run on the currently supported versions of Python on bo **Running the Tests** Each virtual machine within GitHub actions starts in a fresh state with no -software or source installed or downloaded. Therefore, you must clone the repository using the ``checkout`` action, set up Python, and install the necessary testing dependencies. +software or source installed or downloaded. Therefore, you must clone the +repository using the ``checkout`` action, set up Python, and install the +necessary testing dependencies. .. code:: @@ -253,7 +328,7 @@ If you are using ``setup.py``, your installation step is: pip install -r requirements_test.txt -If you are using ``pyproject.toml`` with the ``poetry`` build system, your +If you are using ``pyproject.toml`` with the `poetry`_ build system, your installation step is: .. code:: yaml @@ -272,14 +347,13 @@ Run the unit tests via ``pytest`` with: working-directory: tests run: pytest --cov ansys.product.library - .. note:: - Replace ``ansys.product.library`` with your library name. This should match how it - would be imported within Python. For example, rather than + Replace ``ansys.product.library`` with your library name. This should match + how it would be imported within Python. For example, rather than ``ansys-product-library`` use ``ansys.product.library``. Optionally, though highly recommended, upload your unit test coverage to -`codecov.io `_ with:: +`codecov.io`_ with:: .. code:: yaml @@ -287,9 +361,6 @@ Optionally, though highly recommended, upload your unit test coverage to name: 'Upload coverage to Codecov' -See the following section regarding the usage of `codecov.io`_. - - Code Coverage Enforcement ~~~~~~~~~~~~~~~~~~~~~~~~~ One way of enforcing unit test coverage with a project on GitHub is to use the @@ -325,50 +396,18 @@ of your repository: if_ci_failed: error if_no_uploads: error -This requires that each PR has a patch coverage of 90%, meaning that 90% of any source added to the repository (unless ignored) must be covered by unit tests. +This requires that each PR has a patch coverage of 90%, meaning that 90% of any +source added to the repository (unless ignored) must be covered by unit tests. .. note:: This is only a sample configuration. -Test-Driven Development -~~~~~~~~~~~~~~~~~~~~~~~ - - - - -Remote Method Invocation Testing -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In the case of a Remote Method Invocation (RMI)-like method, it is only necessary -to test the method with a basic case and potentially with any edge cases. - -RMI Service Definition: - -.. code:: - - message SendCommand() - - -Python Wrapping - -.. code:: python - - def send_command(command): - """Run a command on the server. - - Parameters - ---------- - command : str - Command to run on the remote server. Should be in the form of - - - - Files Layout ~~~~~~~~~~~~ -PyAnsys libraries should use ``unittest`` or ``pytest`` libraries to run individual -unit tests contained within a ``tests`` directory in the root of the project. The -specific test files for your project should at a minimum include: +PyAnsys libraries should use ``unittest`` or ``pytest`` libraries to run +individual unit tests contained within a ``tests`` directory in the root of the +project. The specific test files for your project should at a minimum include: .. code:: @@ -378,5 +417,10 @@ specific test files for your project should at a minimum include: conftest.py **Requirements File** -The requirements file contains a list of all the libraries that must be installed to -run ``pytest``. No assumption should be made regarding the state of the virtual +The requirements file contains a list of all the libraries that must be +installed to run ``pytest``. No assumption should be made regarding the state +of the virtual + + +.. _poetry: https://python-poetry.org +.. _codecov.io: https://app.codecov.io/gh/pyansys From 5916deb22805420d962f23bfa92146b9baefbba5 Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Thu, 17 Feb 2022 18:56:13 +0100 Subject: [PATCH 52/62] fix CI --- doc/source/guidelines/test_practices.rst | 31 ++++++++++++------------ 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index ceecda35f..e7e525f2c 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -23,14 +23,15 @@ this document contains examples and best practices to help you write them. Sample gRPC Method Test ~~~~~~~~~~~~~~~~~~~~~~~ There are generally two types of libraries part of the PyAnsys project: + * those that interface or wrap functionality of a different Ansys product, service, or application -* tools those that provide functionality -Both types of Python libraries should be tested, but the tests written will depend on -the purpose of the library. For example, a library that is wrapping a gRPC -interface would include tests of the gRPC methods exposed by the proto files -and wrapped by the Python library. They would not be expected to test the -functionality of the server. +* tools those that provide functionality Both types of Python libraries should + be tested, but the tests written will depend on the purpose of the + library. For example, a library that is wrapping a gRPC interface would + include tests of the gRPC methods exposed by the proto files and wrapped by + the Python library. They would not be expected to test the functionality of + the server. For example, if testing the gRPC method ``GetNode``: @@ -164,8 +165,6 @@ Furthermore, any requirements for testing dependencies should be included when using ``setup.py`` within a ``requirements_tests.txt`` file that is installed via:: -.. code:: - pip install -r requirements_tests.txt An alternative is to include requirements for dependencies in the @@ -243,16 +242,16 @@ coverage: input the wrong data type or value can be reasonably tested. -Unit Testing within CI/CD +Unit Testing Within CI/CD ~~~~~~~~~~~~~~~~~~~~~~~~~ Effective CI/CD assumes that unit testing is developed during feature development or bug fixes. However, given the limited scope of the local development environment, it is often not possible to enforce testing on -multiple platforms, or even, unit testing in general. However, with the right +multiple platforms, or even unit testing in general. However, with the right automated CI/CD, such testing can still occur and be enforced automatically. `GitHub Actions`_ is the preferred automated CI/CD platform for running Python -library unit tests for PyAnsys, and can be employed immediately by cloning the +library unit tests for PyAnsys, and it can be used immediately by cloning the project `template `_. If you are unfamiliar with GitHub Actions, see `GitHub Actions`_ for an overview. @@ -302,8 +301,8 @@ Linux:: **Running the Tests** -Each virtual machine within GitHub actions starts in a fresh state with no -software or source installed or downloaded. Therefore, you must clone the +Each virtual machine within GitHub Actions starts in a fresh state with no +software or source downloaded or installed. Therefore, you must clone the repository using the ``checkout`` action, set up Python, and install the necessary testing dependencies. @@ -353,7 +352,7 @@ Run the unit tests via ``pytest`` with: ``ansys-product-library`` use ``ansys.product.library``. Optionally, though highly recommended, upload your unit test coverage to -`codecov.io`_ with:: +`codecov.io`_ with: .. code:: yaml @@ -364,8 +363,8 @@ Optionally, though highly recommended, upload your unit test coverage to Code Coverage Enforcement ~~~~~~~~~~~~~~~~~~~~~~~~~ One way of enforcing unit test coverage with a project on GitHub is to use the -**codecov.io CI Bot** to enforce minimum patch (and optionally project) -coverage. As this application is already available to the `PyAnsys Organization +codecov.io to enforce minimum patch (and optionally project) coverage. As this +application is already available to the `PyAnsys Organization `_, simply add the following to the root directory of your repository: From 63ae117517a62862fe1477d8b4a494ed73bd0eb9 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Fri, 18 Feb 2022 12:19:00 +0100 Subject: [PATCH 53/62] Update doc/source/guidelines/test_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/guidelines/test_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index e7e525f2c..fd21792a1 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -406,7 +406,7 @@ Files Layout ~~~~~~~~~~~~ PyAnsys libraries should use ``unittest`` or ``pytest`` libraries to run individual unit tests contained within a ``tests`` directory in the root of the -project. The specific test files for your project should at a minimum include: +project. The specific test files for your project should at a minimum include: .. code:: From 7348521c24998344288da5daa6ecd4b963a66f9c Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Fri, 18 Feb 2022 12:19:29 +0100 Subject: [PATCH 54/62] Update doc/source/guidelines/test_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/guidelines/test_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index fd21792a1..0101e8541 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -349,7 +349,7 @@ Run the unit tests via ``pytest`` with: .. note:: Replace ``ansys.product.library`` with your library name. This should match how it would be imported within Python. For example, rather than - ``ansys-product-library`` use ``ansys.product.library``. + ``ansys-product-library``, use ``ansys.product.library``. Optionally, though highly recommended, upload your unit test coverage to `codecov.io`_ with: From 92bf4db85102360a760d5958b9765608e95581b3 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Fri, 18 Feb 2022 12:19:40 +0100 Subject: [PATCH 55/62] Update doc/source/guidelines/test_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/guidelines/test_practices.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index 0101e8541..6f6b950a0 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -327,8 +327,8 @@ If you are using ``setup.py``, your installation step is: pip install -r requirements_test.txt -If you are using ``pyproject.toml`` with the `poetry`_ build system, your -installation step is: +If you are using ``pyproject.toml`` with the `poetry`_ build system, install +with: .. code:: yaml From 6dcbf9e7bfd2617c9d73faa9acd6502707697ea4 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Fri, 18 Feb 2022 12:19:50 +0100 Subject: [PATCH 56/62] Update doc/source/guidelines/test_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/guidelines/test_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index 6f6b950a0..22a42714f 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -237,7 +237,7 @@ coverage: .. note:: You should only avoid coverage of parts of your library where you cannot reasonably test without an extensive testing suite or setup. Most methods - and classes, including edge cases, can be reasonable tested. Even parts of + and classes, including edge cases, can be reasonably tested. Even parts of your code that raise errors like ``TypeError`` or ``ValueError`` when users input the wrong data type or value can be reasonably tested. From 96ad9a56c720e192f4fa73bb2da812e53480e40a Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:07:07 +0100 Subject: [PATCH 57/62] Update doc/source/guidelines/test_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/guidelines/test_practices.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index 22a42714f..397abfb16 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -142,11 +142,11 @@ Example test: output = srv.send_command("CREATE,1") assert "Created 1" in output -Note that this test only validates the command ``"CREATE,1"`` has been +Note that this test only validates that the command ``"CREATE,1"`` has been received, executed, and sent back to the client. It does not validate all -commands, but nor is it necessary to do this unless there are edge cases -(e.g. characters that cannot be streamed or dealing with long running -commands). +commands, but doing this is necessary only if there are edge cases, which +include characters that cannot be streamed or using long-running +commands. Testing Framework From 7663139552abb25829b7016cf2ef74c11ef24b43 Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:08:32 +0100 Subject: [PATCH 58/62] Update doc/source/guidelines/test_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/guidelines/test_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index 397abfb16..5993f9ccc 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -316,7 +316,7 @@ necessary testing dependencies. python-version: ${{ matrix.python-version }} -If you are using ``setup.py``, your installation step is: +If you are using ``setup.py``, install with: .. code:: yaml From 64d0207cbbdb018dc65f38d3ad118a06e8461afd Mon Sep 17 00:00:00 2001 From: Maxime Rey <87315832+MaxJPRey@users.noreply.github.com> Date: Fri, 18 Feb 2022 14:08:47 +0100 Subject: [PATCH 59/62] Update doc/source/guidelines/test_practices.rst Co-authored-by: Kathy Pippert <84872299+PipKat@users.noreply.github.com> --- doc/source/guidelines/test_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index 5993f9ccc..d471f0629 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -184,7 +184,7 @@ When using ``pytest``, test via:: .. note:: We recommend that you place the source of your library within the ``src`` - direction rather than having your Python library source directly within the + directory rather than having your Python library source directly within the repository root directory. This helps you avoid testing the source of the repository and rather the installed package. This helps to catch errors caused by files that might be missed by the installer, including any C From 5706bf5b96b9f061a5a2ee7536345bc3ee3f2810 Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Fri, 18 Feb 2022 14:21:51 +0100 Subject: [PATCH 60/62] End the sentence for the requirement files. --- doc/source/guidelines/test_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index d471f0629..f4cc9c056 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -418,7 +418,7 @@ project. The specific test files for your project should at a minimum include: **Requirements File** The requirements file contains a list of all the libraries that must be installed to run ``pytest``. No assumption should be made regarding the state -of the virtual +of the virtual environment and the packages already installed. .. _poetry: https://python-poetry.org From 953ce59f88ad3d46641db1841b8fa54acc603230 Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Sat, 19 Feb 2022 14:43:27 +0100 Subject: [PATCH 61/62] add testing methodology --- doc/source/guidelines/test_practices.rst | 332 ++++++++++++++++------- 1 file changed, 231 insertions(+), 101 deletions(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index e7e525f2c..780ea127d 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -1,7 +1,7 @@ .. _testing: Testing -------- +======= Unit and integration testing is critical for the successful continuous integration and delivery of any program or libraries belonging to the PyAnsys project. @@ -14,26 +14,134 @@ last test. Furthermore, all test cases do not have to be implemented at once but rather gradually as the code evolves TDD has been created by Kent Beck in the 1990's as part of the Extreme Programming software development process -.. _Test driven development: https://en.wikipedia.org/wiki/Test-driven_development - We recommend that you follow TDD when developing your PyAnsys project, and this document contains examples and best practices to help you write them. -Sample gRPC Method Test -~~~~~~~~~~~~~~~~~~~~~~~ -There are generally two types of libraries part of the PyAnsys project: +Testing Methodology +------------------- +You should consider three levels of testing for your PyAnsys library: unit, +integration, and functional testing. + +**Unit** testing validates your library at the lowest possible level, isolating +individual classes and methods without any communication with other libraries +or services. + +**Integration** testing validates that your library works in the context of an +application or software stack. For example, if your library extends or wraps +the functionality of an external service, you would need to test that service +in conjunction with your library. On GitHub, the ideal approach for this would +be to start your service via docker and test accordingly. You should still be +testing at the individual class or method level, but you can now test how +multiple libraries or services interact. This is mandatory for testing APIs and +is preferred over mocking the service. + +**Functional** testing should be used for validating workflows or long running +examples. For example, if you have a library that wraps a CAD service, you +would validate that you can create complex geometry while directly interfacing +with the service. Functional tests are great at discovering edge cases that are +not normally found at the unit or integration level, but functional testing +should be limited to only a handful of examples as these tend to be long +running and difficult to validate. + +Each PyAnsys project should have all three levels of testing implemented in its +testing framework. Consider implementing functional tests as examples within +your project's documentation examples. This will allow you to write helpful +user-facing tests while accomplishing functional testing. + + +Unit Testing +~~~~~~~~~~~~ +Unit testing tests at the lowest possible level isolated +from other applications or libraries. For Python tool libraries like +`ansys-tools-protoc-helper`_, unit testing is sufficient to get high coverage +(> 80%) of your library while actually testing the library. + +.. _ansys-tools-protoc-helper: https://github.com/ansys/ansys-tools-protoc-helper + +These tests should be written to test a single method in isolation. For +example, if you have a method that deserializes chunks: + +.. code:: python + + def parse_chunks(chunks): + """Deserialize gRPC chunks into a numpy array + + Parameters + ---------- + chunks : generator + generator from grpc. Each chunk contains a bytes payload + + dtype : np.dtype + Numpy data type to interpert chunks as. + + Returns + ------- + array : np.ndarray + Deserialized numpy array. + + """ + arrays = [] + for chunk in chunks: + arrays.append(np.frombuffer(chunk.payload, ANSYS_VALUE_TYPE[chunk.value_type])) + + return np.hstack(arrays) + +Your ``test_parse_chunks.py`` would then be: + +.. code:: python + + + import pytest + import numpy as np + from ansys.api.mapdl.v0 import ansys_kernel_pb2 as anskernel + + from ansys.mapdl.core.common_grpc import parse_chunks + + DEFAULT_CHUNKSIZE = 256*1024 # 256 kB + + + @pytest.fixture() + def sample_array(): + """Generate a non-trivial (n x 3) float array.""" + sz = np.random.randint(100000, 200000) + array = np.random.random((sz, 3)).astype(np.float64) + assert array.nbytes > DEFAULT_CHUNKSIZE + return array + + + def serialize_chunks(array): + """Serialize an array into chunks.""" + # convert to raw + raw = array.tobytes() + value_type = 5 # float64 + + i = 0 + while True: + piece = raw[i:i + DEFAULT_CHUNKSIZE] + i += DEFAULT_CHUNKSIZE + length = len(piece) + if length == 0: + break + yield anskernel.Chunk(payload=piece, size=length, value_type=value_type) + + + def test_deserialize_chunks(sample_array): + parsed_array = parse_chunks(serialize_chunks(sample_array)) + parsed_array = parsed_array.reshape(-1, 3) + assert np.allclose(sample_array, parsed_array) -* those that interface or wrap functionality of a different Ansys product, - service, or application -* tools those that provide functionality Both types of Python libraries should - be tested, but the tests written will depend on the purpose of the - library. For example, a library that is wrapping a gRPC interface would - include tests of the gRPC methods exposed by the proto files and wrapped by - the Python library. They would not be expected to test the functionality of - the server. +This assumes that you do not have a ``serialize_chunks`` function within your +library. If you did, you could exclude it from ``test_parse_chunks.py`` -For example, if testing the gRPC method ``GetNode``: + +Integration Testing - Wrapped Service Methods +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Any PyAnsys library that provides functionality by wrapping a gRPC interface +should include tests of the gRPC methods exposed by the proto files and wrapped +by the Python library. They would not be expected to test the functionality of +the server, but rather the APIs exposed by the server. For example, if testing +the gRPC method ``GetNode``: .. code:: @@ -59,8 +167,8 @@ For example, if testing the gRPC method ``GetNode``: // other methods } -Then your unit test would test the wrapped python function (for example, -``get_node``). You might implement the ``get_node`` method with: +Then your integration test would test the wrapped Python function. If the +Python library wraps this gRPC method with a ``get_node`` method: .. code:: python @@ -104,25 +212,28 @@ Your test would be implemented within ``tests/test_nodes.py``: srv.create_node(node_index, node_coord*) assert srv.get_node(node_index) == node_coord -The goal of the unit test should be to test the wrapping of the -interface rather than the product or service itself. In the case of -``GetNode``, this method should have already been tested when designing and -developing the service. +The goal of the unit test should be to test the API rather than the product or +service itself. In the case of ``GetNode``, this method should have already +been tested when designing and developing the service. + -Remote Method Invocation Testing -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In the case of a Remote Method Invocation (RMI)-like method, it is only necessary -to test the method with a basic case and potentially with any edge cases. +Integration Testing - Remote Method Invocation Testing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In the case of a Remote Method Invocation (RMI)-like method, it is only +necessary to test the method with a basic case and potentially with any edge +cases. A RMI-like API might send and receive strings that are excuted on the +server using a custom API or language only available within the context of the +service. -RMI Service Definition: +For example, if a method has a RMI service definition of: .. code:: message SendCommand() -Python wrapping: +and a Python wrapping: .. code:: python @@ -134,7 +245,7 @@ Python wrapping: command : str Command to run on the remote server. -Example test: +Your exmaple test would be: .. code:: python @@ -149,8 +260,25 @@ commands, but nor is it necessary to do this unless there are edge cases commands). +Functional Testing +~~~~~~~~~~~~~~~~~~ +Functional testing should test the Python library using scripts or examples +that are expected to be excuted by the user. Unlike unit or integration +testing, these functional tests are testing the library as a whole by calling +several methods to accomplish a task. These tests should only be run after unit +and integration testing is complete, and they should be run outside the +``pytest`` framework and ideally while building documentation with +`sphinx-gallery`_. + +.. note:: + Functional tests should not contribute to global library coverage. Testing + should always be done on individual function or methods. + +.. _sphinx-gallery: https://sphinx-gallery.github.io/ + + Testing Framework -~~~~~~~~~~~~~~~~~ +----------------- For consistency, PyAnsys tools and libraries should use either the `unittest `_ or `pytest `_ frameworks for unit testing. As described in @@ -191,8 +319,28 @@ When using ``pytest``, test via:: extensions or additional internal packages. +Files Layout +~~~~~~~~~~~~ +PyAnsys libraries should use ``unittest`` or ``pytest`` libraries to run +individual unit tests contained within a ``tests`` directory in the root of the +project. The specific test files for your project should at a minimum include: + +.. code:: + + requirements_tests.py + tests/ + test_.py + conftest.py + +Requirements File +~~~~~~~~~~~~~~~~~ +The requirements file contains a list of all the libraries that must be +installed to run ``pytest``. No assumption should be made regarding the state +of the virtual + + Coverage -~~~~~~~~ +-------- Given that Python is an interpreted language, developers of Python libraries should aim to have high coverage for their libraries as only syntax errors can be caught during the almost trivial compile time. Coverage is defined as parts @@ -241,9 +389,50 @@ coverage: your code that raise errors like ``TypeError`` or ``ValueError`` when users input the wrong data type or value can be reasonably tested. - -Unit Testing Within CI/CD +Code Coverage Enforcement ~~~~~~~~~~~~~~~~~~~~~~~~~ +One way of enforcing unit test coverage with a project on GitHub is to use the +codecov.io to enforce minimum patch (and optionally project) coverage. As this +application is already available to the `PyAnsys Organization +`_, simply add the following to the root directory +of your repository: + +**/codecov.yml** + +.. code:: yaml + + comment: + layout: "diff" + behavior: default + + coverage: + status: + project: + default: + # basic + # target: 50% + threshold: 0% + # advanced + if_not_found: success + if_ci_failed: error + if_no_uploads: error + patch: + default: + # basic + target: 90% + if_not_found: success + if_ci_failed: error + if_no_uploads: error + +This requires that each PR has a patch coverage of 90%, meaning that 90% of any +source added to the repository (unless ignored) must be covered by unit tests. + +.. note:: + This is only a sample configuration. + + +Unit Testing on GitHub via CI/CD +-------------------------------- Effective CI/CD assumes that unit testing is developed during feature development or bug fixes. However, given the limited scope of the local development environment, it is often not possible to enforce testing on @@ -257,14 +446,13 @@ unfamiliar with GitHub Actions, see `GitHub Actions`_ for an overview. .. _GitHub Actions: https://github.com/features/actions -**Sample Workflow** - The following sections describe the usage of a simple GitHub workflow for a PyAnsys library: -**Setup** - -Include the job name when it should be run at the top of the workflow ``.yml``:: +Setup +~~~~~ +Include the job name when it should be run at the top of the workflow +``.yml``:: name: Unit Testing @@ -282,8 +470,9 @@ Take note that this workflow runs on all pull requests and on demand with ``main`` branch. This ensures that CI/CD is not run twice on every commit for each PR, which may saturate available build or testing machines. -**Job Description** +Job Description +~~~~~~~~~~~~~~~ PyAnsys libraries should run on the currently supported versions of Python on both Windows and Linux (and ideally on Mac OS). Therefore, it is necessary to also test on both Linux and Windows for these versions of Python. Use the @@ -299,8 +488,9 @@ Linux:: os: [windows-latest, ubuntu-latest] python-version: ['3.7', '3.8', '3.9', '3.10'] -**Running the Tests** +Running the Tests +~~~~~~~~~~~~~~~~~ Each virtual machine within GitHub Actions starts in a fresh state with no software or source downloaded or installed. Therefore, you must clone the repository using the ``checkout`` action, set up Python, and install the @@ -360,66 +550,6 @@ Optionally, though highly recommended, upload your unit test coverage to name: 'Upload coverage to Codecov' -Code Coverage Enforcement -~~~~~~~~~~~~~~~~~~~~~~~~~ -One way of enforcing unit test coverage with a project on GitHub is to use the -codecov.io to enforce minimum patch (and optionally project) coverage. As this -application is already available to the `PyAnsys Organization -`_, simply add the following to the root directory -of your repository: - -**/codecov.yml** - -.. code:: yaml - - comment: - layout: "diff" - behavior: default - - coverage: - status: - project: - default: - # basic - # target: 50% - threshold: 0% - # advanced - if_not_found: success - if_ci_failed: error - if_no_uploads: error - patch: - default: - # basic - target: 90% - if_not_found: success - if_ci_failed: error - if_no_uploads: error - -This requires that each PR has a patch coverage of 90%, meaning that 90% of any -source added to the repository (unless ignored) must be covered by unit tests. - -.. note:: - This is only a sample configuration. - - -Files Layout -~~~~~~~~~~~~ -PyAnsys libraries should use ``unittest`` or ``pytest`` libraries to run -individual unit tests contained within a ``tests`` directory in the root of the -project. The specific test files for your project should at a minimum include: - -.. code:: - - requirements_tests.py - tests/ - test_.py - conftest.py - -**Requirements File** -The requirements file contains a list of all the libraries that must be -installed to run ``pytest``. No assumption should be made regarding the state -of the virtual - - -.. _poetry: https://python-poetry.org +.. _Test driven development: https://en.wikipedia.org/wiki/Test-driven_development .. _codecov.io: https://app.codecov.io/gh/pyansys +.. _poetry: https://python-poetry.org From 14c1915169a5dfab2751579e154f163d6574ca31 Mon Sep 17 00:00:00 2001 From: Maxime Rey Date: Sun, 20 Feb 2022 20:01:03 +0100 Subject: [PATCH 62/62] Title underline was too short and prevented the doc to be buit. --- doc/source/guidelines/test_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/guidelines/test_practices.rst b/doc/source/guidelines/test_practices.rst index 676b5d4fe..228d20b28 100644 --- a/doc/source/guidelines/test_practices.rst +++ b/doc/source/guidelines/test_practices.rst @@ -219,7 +219,7 @@ been tested when designing and developing the service. Integration Testing - Remote Method Invocation Testing -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the case of a Remote Method Invocation (RMI)-like method, it is only necessary to test the method with a basic case and potentially with any edge cases. A RMI-like API might send and receive strings that are excuted on the