From 69e6114e8479df27958be45e328e313ebaf3c39b Mon Sep 17 00:00:00 2001 From: Richard Ward Date: Thu, 17 Jul 2025 00:14:08 +0100 Subject: [PATCH] Add unit tests and GitHub Action --- .github/workflows/python-tests.yml | 20 ++++++++++++++++++++ tests/test_export.py | 13 +++++++++++++ tests/test_mechanisms.py | 15 +++++++++++++++ tests/test_primitives.py | 23 +++++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 .github/workflows/python-tests.yml create mode 100644 tests/test_export.py create mode 100644 tests/test_mechanisms.py create mode 100644 tests/test_primitives.py diff --git a/.github/workflows/python-tests.yml b/.github/workflows/python-tests.yml new file mode 100644 index 0000000..94ee9fc --- /dev/null +++ b/.github/workflows/python-tests.yml @@ -0,0 +1,20 @@ +name: Python unit tests + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + - name: Install dependencies + run: | + pip install pytest trimesh shapely + - name: Run tests + env: + PYTHONPATH: ${{ github.workspace }} + run: pytest -vv diff --git a/tests/test_export.py b/tests/test_export.py new file mode 100644 index 0000000..ea3d686 --- /dev/null +++ b/tests/test_export.py @@ -0,0 +1,13 @@ +import os +import pytest +import trimesh +from parametric_cad.primitives.box import Box +from parametric_cad.export.stl import STLExporter + + +def test_stl_exporter(tmp_path): + exporter = STLExporter(output_dir=tmp_path) + box = Box(1.0, 1.0, 1.0) + path = exporter.export_mesh(box, "test_box", preview=False) + assert os.path.isfile(path) + assert path == str(tmp_path / "test_box.stl") diff --git a/tests/test_mechanisms.py b/tests/test_mechanisms.py new file mode 100644 index 0000000..e9e6752 --- /dev/null +++ b/tests/test_mechanisms.py @@ -0,0 +1,15 @@ +import numpy as np +import pytest +import trimesh + +from parametric_cad.mechanisms.butthinge import ButtHinge + + +def test_butthinge_mesh_and_translation(): + hinge = ButtHinge() + mesh = hinge.mesh() + assert isinstance(mesh, trimesh.Trimesh) + original_centroid = mesh.centroid.copy() + hinge.at(1.0, 2.0, 3.0) + translated_centroid = hinge.mesh().centroid + assert np.allclose(translated_centroid, original_centroid + [1.0, 2.0, 3.0]) diff --git a/tests/test_primitives.py b/tests/test_primitives.py new file mode 100644 index 0000000..e25f248 --- /dev/null +++ b/tests/test_primitives.py @@ -0,0 +1,23 @@ +import pytest +import numpy as np +import trimesh +from math import cos, pi + +from parametric_cad.primitives.box import Box +from parametric_cad.primitives.gear import SpurGear + + +def test_box_mesh_extents_and_position(): + box = Box(1.0, 2.0, 3.0).at(1.0, 1.0, 1.0) + mesh = box.mesh() + assert np.allclose(mesh.centroid, [1.0, 1.0, 1.0]) + assert mesh.extents[0] == pytest.approx(1.0) + assert mesh.extents[1] == pytest.approx(2.0) + assert mesh.extents[2] == pytest.approx(3.0) + + +def test_spur_gear_diameters(): + gear = SpurGear(module=2.0, teeth=10) + assert gear.pitch_diameter == pytest.approx(20.0) + expected_base = gear.pitch_diameter * cos(20 * pi / 180) + assert gear.base_diameter == pytest.approx(expected_base)