From bda0a6a719501829f2a5427a04f4cca38da5c826 Mon Sep 17 00:00:00 2001 From: Ami Fischman Date: Sat, 22 Feb 2025 10:35:50 -0800 Subject: [PATCH] Run tests in parallel by default, and update CONTRIBUTING.md to recommend this flow. test_mesher.py was reusing the same filename across tests which meant that when running in parallel tests would stomp on each other. Robustified by having each test use a distinct file name. --- .github/workflows/test.yml | 2 +- CONTRIBUTING.md | 6 +++--- pyproject.toml | 1 + tests/test_mesher.py | 42 +++++++++++++++++++++++++------------- 4 files changed, 33 insertions(+), 18 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b636f042..f35c15f1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,4 +23,4 @@ jobs: python-version: ${{ matrix.python-version }} - name: test run: | - python -m pytest + python -m pytest -n auto diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 115577ab..c1344c35 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,10 +3,10 @@ tests, ensure they build and pass, and ensure that `pylint` and `mypy` are happy with your code. - Install `pip` following their [documentation](https://pip.pypa.io/en/stable/installation/). -- Install development dependencies: `pip install pylint pytest mypy sphinx black` -- Install docs dependencies: `pip install -r docs/requirements.txt` (might need to comment out the build123d line in that file) +- Install development dependencies: `pip install -e .[development]` +- Install docs dependencies: `pip install -e .[docs]` - Install `build123d` in editable mode from current dir: `pip install -e .` -- Run tests with: `python -m pytest` +- Run tests with: `python -m pytest -n auto` - Build docs with: `cd docs && make html` - Check added files' style with: `pylint ` - Check added files' type annotations with: `mypy ` diff --git a/pyproject.toml b/pyproject.toml index b5aa3330..167ed019 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,6 +64,7 @@ development = [ "wheel", "pytest", "pytest-cov", + "pytest-xdist", "pylint", "mypy", "black", diff --git a/tests/test_mesher.py b/tests/test_mesher.py index 9547d08b..65edafff 100644 --- a/tests/test_mesher.py +++ b/tests/test_mesher.py @@ -2,7 +2,8 @@ from packaging.specifiers import SpecifierSet from pathlib import Path from os import fsdecode, fsencode -import time +import sys +import tempfile import pytest @@ -18,6 +19,12 @@ from build123d.mesher import Mesher +def temp_3mf_file(): + caller = sys._getframe(1) + prefix = f"build123d_{caller.f_locals.get('self').__class__.__name__}_{caller.f_code.co_name}" + return tempfile.mktemp(suffix=".3mf", prefix=prefix) + + class DirectApiTestCase(unittest.TestCase): def assertTupleAlmostEquals( self, @@ -47,11 +54,12 @@ def test_version(self): def test_units(self): for unit in Unit: + filename = temp_3mf_file() exporter = Mesher(unit=unit) exporter.add_shape(Solid.make_box(1, 1, 1)) - exporter.write("test.3mf") + exporter.write(filename) importer = Mesher() - _shape = importer.read("test.3mf") + _shape = importer.read(filename) self.assertEqual(unit, importer.model_unit) def test_vertex_and_triangle_counts(self): @@ -73,9 +81,10 @@ def test_add_meta_data(self): exporter.add_shape(Solid.make_box(1, 1, 1)) exporter.add_meta_data("test_space", "test0", "some data", "str", True) exporter.add_meta_data("test_space", "test1", "more data", "str", True) - exporter.write("test.3mf") + filename = temp_3mf_file() + exporter.write(filename) importer = Mesher() - _shape = importer.read("test.3mf") + _shape = importer.read(filename) imported_meta_data: list[dict] = importer.get_meta_data() self.assertEqual(imported_meta_data[0]["name_space"], "test_space") self.assertEqual(imported_meta_data[0]["name"], "test0") @@ -90,9 +99,10 @@ def test_add_code(self): exporter = Mesher() exporter.add_shape(Solid.make_box(1, 1, 1)) exporter.add_code_to_metadata() - exporter.write("test.3mf") + filename = temp_3mf_file() + exporter.write(filename) importer = Mesher() - _shape = importer.read("test.3mf") + _shape = importer.read(filename) source_code = importer.get_meta_data_by_key("build123d", "test_mesher.py") self.assertEqual(len(source_code), 2) self.assertEqual(source_code["type"], "python") @@ -118,9 +128,10 @@ def test_properties(self): part_number=str(mesh_type.value), uuid_value=test_uuid, ) - exporter.write("test.3mf") + filename = temp_3mf_file() + exporter.write(filename) importer = Mesher() - shape = importer.read("test.3mf") + shape = importer.read(filename) self.assertEqual(shape[0].label, name) self.assertEqual(importer.mesh_count, 1) properties = importer.get_mesh_properties() @@ -141,9 +152,10 @@ def test_add_shape(self): red_shape.color = Color("red") red_shape.label = "red" exporter.add_shape([blue_shape, red_shape]) - exporter.write("test.3mf") + filename = temp_3mf_file() + exporter.write(filename) importer = Mesher() - box, cone = importer.read("test.3mf") + box, cone = importer.read(filename) self.assertVectorAlmostEquals(box.bounding_box().size, (1, 1, 1), 2) self.assertVectorAlmostEquals(box.bounding_box().size, (1, 1, 1), 2) self.assertEqual(len(box.clean().faces()), 6) @@ -158,9 +170,10 @@ def test_add_compound(self): cone = Solid.make_cone(1, 0, 2).locate(Location((0, -1, 0))) shape_assembly = Compound([box, cone]) exporter.add_shape(shape_assembly) - exporter.write("test.3mf") + filename = temp_3mf_file() + exporter.write(filename) importer = Mesher() - shapes = importer.read("test.3mf") + shapes = importer.read(filename) self.assertEqual(importer.mesh_count, 2) @@ -216,7 +229,8 @@ def test_degenerate_import(self): "format", (Path, fsencode, fsdecode), ids=["path", "bytes", "str"] ) def test_pathlike_mesher(tmp_path, format): - path = format(tmp_path / "test.3mf") + filename = temp_3mf_file() + path = format(tmp_path / filename) exporter, importer = Mesher(), Mesher() exporter.add_shape(Solid.make_box(1, 1, 1)) exporter.write(path)