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.
This commit is contained in:
Ami Fischman 2025-02-22 10:35:50 -08:00
parent aeb6b32b65
commit bda0a6a719
4 changed files with 33 additions and 18 deletions

View file

@ -23,4 +23,4 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: test
run: |
python -m pytest
python -m pytest -n auto

View file

@ -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 <path/to/file.py>`
- Check added files' type annotations with: `mypy <path/to/file.py>`

View file

@ -64,6 +64,7 @@ development = [
"wheel",
"pytest",
"pytest-cov",
"pytest-xdist",
"pylint",
"mypy",
"black",

View file

@ -2,7 +2,8 @@ import unittest, uuid
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.geometry import Axis, Color, Location, Vector, VectorLike
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 @@ class TestProperties(unittest.TestCase):
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 @@ class TestMetaData(unittest.TestCase):
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 @@ class TestMetaData(unittest.TestCase):
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 @@ class TestMeshProperties(unittest.TestCase):
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 @@ class TestAddShape(DirectApiTestCase):
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 @@ class TestAddShape(DirectApiTestCase):
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 @@ class TestImportDegenerateTriangles(unittest.TestCase):
"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)