This commit is contained in:
24
tests/gridfinity-rebuilt-baseplate.json
Normal file
24
tests/gridfinity-rebuilt-baseplate.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"fileFormatVersion": "1",
|
||||
"parameterSets": {
|
||||
"Default": {
|
||||
"$fa": "8",
|
||||
"$fs": "0.25",
|
||||
"d_screw": "3.3500000000000001",
|
||||
"d_screw_head": "5",
|
||||
"distancex": "0",
|
||||
"distancey": "0",
|
||||
"chamfer_holes": "true",
|
||||
"crush_ribs": "true",
|
||||
"enable_magnet": "true",
|
||||
"fitx": "0",
|
||||
"fity": "0",
|
||||
"gridx": "1",
|
||||
"gridy": "1",
|
||||
"n_screws": "1",
|
||||
"screw_spacing": "0.5",
|
||||
"style_hole": "1",
|
||||
"style_plate": "2"
|
||||
}
|
||||
}
|
||||
}
|
||||
36
tests/gridfinity-rebuilt-bins.json
Normal file
36
tests/gridfinity-rebuilt-bins.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"fileFormatVersion": "1",
|
||||
"parameterSets": {
|
||||
"Default": {
|
||||
"$fa": "8",
|
||||
"$fs": "0.25",
|
||||
"c_chamfer": "0.5",
|
||||
"c_depth": "1",
|
||||
"c_orientation": "2",
|
||||
"cd": "10",
|
||||
"cdivx": "0",
|
||||
"cdivy": "0",
|
||||
"ch": "1",
|
||||
"chamfer_holes": "true",
|
||||
"crush_ribs": "true",
|
||||
"div_base_x": "0",
|
||||
"div_base_y": "0",
|
||||
"divx": "0",
|
||||
"divy": "0",
|
||||
"enable_zsnap": "false",
|
||||
"gridx": "1",
|
||||
"gridy": "1",
|
||||
"gridz": "6",
|
||||
"gridz_define": "0",
|
||||
"height_internal": "0",
|
||||
"magnet_holes": "false",
|
||||
"only_corners": "false",
|
||||
"printable_hole_top": "true",
|
||||
"refined_holes": "true",
|
||||
"scoop": "0",
|
||||
"screw_holes": "false",
|
||||
"style_lip": "0",
|
||||
"style_tab": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
28
tests/gridfinity-spiral-vase.json
Normal file
28
tests/gridfinity-spiral-vase.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"fileFormatVersion": "1",
|
||||
"parameterSets": {
|
||||
"Default": {
|
||||
"$fa": "8",
|
||||
"$fs": "0.25",
|
||||
"a_tab": "40",
|
||||
"bottom_layer": "3",
|
||||
"enable_funnel": "true",
|
||||
"enable_holes": "true",
|
||||
"enable_inset": "true",
|
||||
"enable_lip": "true",
|
||||
"enable_pinch": "true",
|
||||
"enable_scoop_chamfer": "true",
|
||||
"enable_zsnap": "false",
|
||||
"gridx": "1",
|
||||
"gridy": "1",
|
||||
"gridz": "6",
|
||||
"gridz_define": "0",
|
||||
"layer": "0.35",
|
||||
"n_divx": "2",
|
||||
"nozzle": "0.6",
|
||||
"style_base": "0",
|
||||
"style_tab": "0",
|
||||
"type": "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
167
tests/openscad_runner.py
Normal file
167
tests/openscad_runner.py
Normal file
@@ -0,0 +1,167 @@
|
||||
"""
|
||||
Helpful classes for running OpenScad from Python.
|
||||
@Copyright Arthur Moore 2024 MIT License
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
from dataclasses import dataclass, is_dataclass, asdict
|
||||
from pathlib import Path
|
||||
from tempfile import NamedTemporaryFile
|
||||
from typing import NamedTuple, Optional
|
||||
|
||||
class DataClassJSONEncoder(json.JSONEncoder):
|
||||
'''Allow json serialization'''
|
||||
def default(self, o):
|
||||
if is_dataclass(o):
|
||||
return asdict(o)
|
||||
# Let the base class default method raise the TypeError
|
||||
return super().default(o)
|
||||
|
||||
class Vec3(NamedTuple):
|
||||
'''Simple 3d Vector (x, y, z)'''
|
||||
x: float
|
||||
y: float
|
||||
z: float
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class CameraArguments:
|
||||
"""
|
||||
Controls the camera position when outputting to png format.
|
||||
@see `openscad -h`.
|
||||
Supports fluid interface.
|
||||
"""
|
||||
translate: Vec3
|
||||
rotate: Vec3
|
||||
distance: float
|
||||
|
||||
def with_translation(self, new_translate: Vec3) -> CameraArguments:
|
||||
return CameraArguments(translate=new_translate, rotate=self.rotate, distance=self.distance)
|
||||
|
||||
def with_rotation(self, new_rotate: Vec3) -> CameraArguments:
|
||||
return CameraArguments(translate=self.translate, rotate=new_rotate, distance=self.distance)
|
||||
|
||||
def with_distance(self, new_distance: float) -> CameraArguments:
|
||||
return CameraArguments(translate=self.translate, rotate=rotate, distance=new_distance)
|
||||
|
||||
def as_argument(self) -> str:
|
||||
return '--camera=' \
|
||||
f'{",".join(map(str,self.translate))},{",".join(map(str,self.rotate))},{self.distance}'
|
||||
|
||||
@dataclass(kw_only=True, frozen=True)
|
||||
class ParameterFile:
|
||||
parameterSets: dict[str, dict]
|
||||
fileFormatVersion: int = 1
|
||||
|
||||
@classmethod
|
||||
def from_json(cls, *pargs, **nargs):
|
||||
"""
|
||||
Wrapper for `json.loads`, with some post-processing.
|
||||
The Customizer saves everything as strings. --Arthur 2024-04-28
|
||||
"""
|
||||
nargs["object_pairs_hook"] = cls.object_pairs_hook
|
||||
file = ParameterFile(**json.loads(*pargs, **nargs))
|
||||
assert(file.fileFormatVersion == 1)
|
||||
return file
|
||||
|
||||
@classmethod
|
||||
def object_pairs_hook(self, pairs: list[tuple]):
|
||||
'''Fixes customizer turning everything into strings'''
|
||||
output = dict(pairs)
|
||||
for (key, value) in output.items():
|
||||
if(type(value) == str):
|
||||
if(value == "true"):
|
||||
output[key] = True
|
||||
continue
|
||||
if(value == "false"):
|
||||
output[key] = False
|
||||
continue
|
||||
try:
|
||||
output[key] = float(value)
|
||||
except ValueError:
|
||||
pass
|
||||
return output
|
||||
|
||||
def set_variable_argument(var: str, val: str) -> [str, str]:
|
||||
"""
|
||||
Allows setting a variable to a particular value.
|
||||
@warning value **can** be a function, but this is called for every file, so may generate 'undefined' warnings.
|
||||
"""
|
||||
return ['-D', f'{var}={str(val)}']
|
||||
|
||||
class CameraRotations:
|
||||
'''Pre-defined useful camera rotations'''
|
||||
Default = Vec3(0,0,0),
|
||||
AngledTop = Vec3(45,0,45)
|
||||
AngledBottom = Vec3(225,0,225)
|
||||
Top = Vec3(45,0,0)
|
||||
|
||||
class OpenScadRunner:
|
||||
'''Helper to run the openscad binary'''
|
||||
scad_file_path: Path
|
||||
openscad_binary_path: Path
|
||||
image_folder_base: Path
|
||||
parameters: Optional[dict]
|
||||
'''If set, a temporary parameter file is created, and used with these variables'''
|
||||
|
||||
WINDOWS_DEFAULT_PATH = 'C:\\Program Files\\OpenSCAD\\openscad.exe'
|
||||
TOP_ANGLE_CAMERA = CameraArguments(Vec3(0,0,0),Vec3(45,0,45),150)
|
||||
|
||||
common_arguments = [
|
||||
#'--hardwarnings', # Does not work when setting variables by using functions
|
||||
'--enable=fast-csg',
|
||||
'--enable=predictible-output',
|
||||
'--imgsize=1280,720',
|
||||
'--view=axes',
|
||||
'--projection=ortho',
|
||||
#"--summary", "all",
|
||||
#"--summary-file", "-"
|
||||
] + \
|
||||
set_variable_argument('$fa', 8) + set_variable_argument('$fs', 0.25)
|
||||
|
||||
def __init__(self, file_path: Path):
|
||||
self.openscad_binary_path = self.WINDOWS_DEFAULT_PATH
|
||||
self.scad_file_path = file_path
|
||||
self.image_folder_base = Path('.')
|
||||
self.camera_arguments = None
|
||||
self.parameters = None
|
||||
|
||||
def create_image(self, args: [str], image_file_name: str) -> subprocess.CompletedProcess:
|
||||
"""
|
||||
Run the code and create an image.
|
||||
@Important The only verification is that no errors occured.
|
||||
There is no verification if the image was created, or the image contents.
|
||||
"""
|
||||
assert(self.scad_file_path.exists())
|
||||
assert(self.image_folder_base.exists())
|
||||
|
||||
image_path = self.image_folder_base.joinpath(image_file_name)
|
||||
command_arguments = self.common_arguments + \
|
||||
([self.camera_arguments.as_argument()] if self.camera_arguments != None else []) + \
|
||||
args + \
|
||||
["-o", str(image_path), str(self.scad_file_path)]
|
||||
#print(command_arguments)
|
||||
|
||||
if self.parameters != None:
|
||||
#print(self.parameters)
|
||||
params = ParameterFile(parameterSets={"python_generated": self.parameters})
|
||||
with NamedTemporaryFile(prefix="gridfinity-rebuilt-", suffix=".json", mode='wt',delete_on_close=False) as file:
|
||||
json.dump(params, file, sort_keys=True, indent=2, cls=DataClassJSONEncoder)
|
||||
file.close()
|
||||
command_arguments += ["-p", file.name, "-P", "python_generated"]
|
||||
return self._run(command_arguments)
|
||||
else:
|
||||
return self._run(command_arguments)
|
||||
|
||||
def _run(self, args: [str]) -> subprocess.CompletedProcess:
|
||||
"""
|
||||
Run openscad with the passed in arguments.
|
||||
"""
|
||||
output = subprocess.run([self.openscad_binary_path]+args, capture_output=True)
|
||||
error_strings = output.stderr.decode().strip().splitlines()
|
||||
if any(line.startswith("ERROR:") for line in error_strings):
|
||||
# OpenSCAD doesn't set an error return if it errors from bad SCAD code!
|
||||
output.returncode = 11
|
||||
output.check_returncode()
|
||||
return output
|
||||
116
tests/test_baseplate.py
Normal file
116
tests/test_baseplate.py
Normal file
@@ -0,0 +1,116 @@
|
||||
"""
|
||||
Tests for gridfinity-rebuilt-baseplate.scad
|
||||
@Copyright Arthur Moore 2024 MIT License
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
import json
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
from openscad_runner import *
|
||||
|
||||
class TestBasePlateHoles(unittest.TestCase):
|
||||
"""
|
||||
Test creating a single base in "gridfinity-spiral-vase.scad"
|
||||
|
||||
Currently only makes sure code runs, and outputs pictures for manual verification.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
parameter_file_path = Path("gridfinity-rebuilt-baseplate.json")
|
||||
parameter_file_data = ParameterFile.from_json(parameter_file_path.read_text())
|
||||
cls.default_parameters = parameter_file_data.parameterSets["Default"]
|
||||
|
||||
def setUp(self):
|
||||
self.scad_runner = OpenScadRunner(Path('../gridfinity-rebuilt-baseplate.scad'))
|
||||
self.scad_runner.image_folder_base = Path('../images/baseplate/')
|
||||
self.scad_runner.parameters = self.default_parameters.copy()
|
||||
self.scad_runner.camera_arguments = CameraArguments(Vec3(0,0,0), CameraRotations.AngledBottom, 150)
|
||||
|
||||
def test_no_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_magnet"] = False
|
||||
vars["style_hole"] = 0
|
||||
self.scad_runner.create_image([], Path('no_holes_bottom.png'))
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
|
||||
self.scad_runner.create_image([], Path('no_holes_top.png'))
|
||||
|
||||
def test_plain_magnet_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_magnet"] = True
|
||||
vars["style_hole"] = 0
|
||||
vars["chamfer_holes"] = False
|
||||
vars["crush_ribs"] = False
|
||||
self.scad_runner.create_image([], Path('magnet_holes_bottom.png'))
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
|
||||
self.scad_runner.create_image([], Path('plain_magnet_holes_top.png'))
|
||||
|
||||
def test_chamfered_magnet_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_magnet"] = True
|
||||
vars["style_hole"] = 0
|
||||
vars["chamfer_holes"] = True
|
||||
vars["crush_ribs"] = False
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
|
||||
self.scad_runner.create_image([], Path('chamfered_magnet_holes.png'))
|
||||
|
||||
def test_ribbed_magnet_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_magnet"] = True
|
||||
vars["style_hole"] = 0
|
||||
vars["chamfer_holes"] = False
|
||||
vars["crush_ribs"] = True
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
|
||||
self.scad_runner.create_image([], Path('ribbed_magnet_holes.png'))
|
||||
|
||||
def test_chamfered_and_ribbed_magnet_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_magnet"] = True
|
||||
vars["style_hole"] = 0
|
||||
vars["chamfer_holes"] = True
|
||||
vars["crush_ribs"] = True
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
|
||||
self.scad_runner.create_image([], Path('chamfered_and_ribbed_magnet_holes.png'))
|
||||
|
||||
def test_only_countersunk_screw_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_magnet"] = False
|
||||
vars["style_hole"] = 1
|
||||
self.scad_runner.create_image([], Path('only_countersunk_screw_holes_bottom.png'))
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
|
||||
self.scad_runner.create_image([], Path('only_countersunk_screw_holes_top.png'))
|
||||
|
||||
def test_only_counterbored_screw_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_magnet"] = False
|
||||
vars["style_hole"] = 2
|
||||
self.scad_runner.create_image([], Path('only_counterbored_screw_holes_bottom.png'))
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
|
||||
self.scad_runner.create_image([], Path('only_counterbored_screw_holes_top.png'))
|
||||
|
||||
def test_magnet_and_countersunk_screw_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_magnet"] = True
|
||||
vars["chamfer_holes"] = False
|
||||
vars["crush_ribs"] = False
|
||||
vars["style_hole"] = 1
|
||||
self.scad_runner.create_image([], Path('magnet_and_countersunk_screw_holes_bottom.png'))
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
|
||||
self.scad_runner.create_image([], Path('magnet_and_countersunk_screw_holes_top.png'))
|
||||
|
||||
def test_magnet_and_counterbored_screw_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_magnet"] = True
|
||||
vars["chamfer_holes"] = False
|
||||
vars["crush_ribs"] = False
|
||||
vars["style_hole"] = 2
|
||||
self.scad_runner.create_image([], Path('magnet_and_counterbored_screw_holes_bottom.png'))
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledTop)
|
||||
self.scad_runner.create_image([], Path('magnet_and_counterbored_screw_holes_top.png'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
150
tests/test_bins.py
Normal file
150
tests/test_bins.py
Normal file
@@ -0,0 +1,150 @@
|
||||
"""
|
||||
Tests for gridfinity-rebuilt-bins.scad
|
||||
@Copyright Arthur Moore 2024 MIT License
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
import json
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
from openscad_runner import *
|
||||
|
||||
class TestBinHoles(unittest.TestCase):
|
||||
"""
|
||||
Test how a single base looks with holes cut out.
|
||||
|
||||
Currently only makes sure code runs, and outputs pictures for manual verification.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
parameter_file_path = Path("gridfinity-rebuilt-bins.json")
|
||||
parameter_file_data = ParameterFile.from_json(parameter_file_path.read_text())
|
||||
cls.default_parameters = parameter_file_data.parameterSets["Default"]
|
||||
|
||||
def setUp(self):
|
||||
self.scad_runner = OpenScadRunner(Path('../gridfinity-rebuilt-bins.scad'))
|
||||
self.scad_runner.image_folder_base = Path('../images/base_hole_options/')
|
||||
self.scad_runner.parameters = self.default_parameters.copy()
|
||||
self.scad_runner.camera_arguments = CameraArguments(Vec3(0,0,0), CameraRotations.AngledBottom, 150)
|
||||
|
||||
def test_no_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = False
|
||||
vars["magnet_holes"] = False
|
||||
vars["screw_holes"] = False
|
||||
self.scad_runner.create_image([], Path('no_holes.png'))
|
||||
|
||||
def test_only_corner_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = True
|
||||
vars["magnet_holes"] = False
|
||||
vars["screw_holes"] = False
|
||||
vars["only_corners"] = True
|
||||
self.scad_runner.create_image([], Path('only_corner_holes.png'))
|
||||
|
||||
def test_refined_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = True
|
||||
vars["magnet_holes"] = False
|
||||
vars["screw_holes"] = False
|
||||
self.scad_runner.create_image([], Path('refined_holes.png'))
|
||||
|
||||
def test_refined_and_screw_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = True
|
||||
vars["magnet_holes"] = False
|
||||
vars["screw_holes"] = True
|
||||
vars["printable_hole_top"] = False
|
||||
self.scad_runner.create_image([], Path('refined_and_screw_holes.png'))
|
||||
|
||||
def test_screw_holes_plain(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = False
|
||||
vars["magnet_holes"] = False
|
||||
vars["screw_holes"] = True
|
||||
vars["printable_hole_top"] = False
|
||||
self.scad_runner.create_image([], Path('screw_holes_plain.png'))
|
||||
|
||||
def test_screw_holes_printable(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = False
|
||||
vars["magnet_holes"] = False
|
||||
vars["screw_holes"] = True
|
||||
vars["printable_hole_top"] = True
|
||||
self.scad_runner.create_image([], Path('screw_holes_printable.png'))
|
||||
|
||||
def test_magnet_holes_plain(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = False
|
||||
vars["magnet_holes"] = True
|
||||
vars["screw_holes"] = False
|
||||
vars["crush_ribs"] = False
|
||||
vars["chamfer_holes"] = False
|
||||
vars["printable_hole_top"] = False
|
||||
self.scad_runner.create_image([], Path('magnet_holes_plain.png'))
|
||||
|
||||
def test_magnet_holes_chamfered(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = False
|
||||
vars["magnet_holes"] = True
|
||||
vars["screw_holes"] = False
|
||||
vars["crush_ribs"] = False
|
||||
vars["chamfer_holes"] = True
|
||||
vars["printable_hole_top"] = False
|
||||
self.scad_runner.create_image([], Path('magnet_holes_chamfered.png'))
|
||||
|
||||
def test_magnet_holes_printable(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = False
|
||||
vars["magnet_holes"] = True
|
||||
vars["screw_holes"] = False
|
||||
vars["crush_ribs"] = False
|
||||
vars["chamfer_holes"] = False
|
||||
vars["printable_hole_top"] = True
|
||||
self.scad_runner.create_image([], Path('magnet_holes_printable.png'))
|
||||
|
||||
def test_magnet_holes_with_crush_ribs(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = False
|
||||
vars["magnet_holes"] = True
|
||||
vars["screw_holes"] = False
|
||||
vars["crush_ribs"] = True
|
||||
vars["chamfer_holes"] = False
|
||||
vars["printable_hole_top"] = False
|
||||
self.scad_runner.create_image([], Path('magnet_holes_with_crush_ribs.png'))
|
||||
|
||||
def test_magnet_and_screw_holes_plain(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = False
|
||||
vars["magnet_holes"] = True
|
||||
vars["screw_holes"] = True
|
||||
vars["crush_ribs"] = False
|
||||
vars["chamfer_holes"] = False
|
||||
vars["printable_hole_top"] = False
|
||||
self.scad_runner.create_image([], Path('magnet_and_screw_holes_plain.png'))
|
||||
|
||||
def test_magnet_and_screw_holes_printable(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = False
|
||||
vars["magnet_holes"] = True
|
||||
vars["screw_holes"] = True
|
||||
vars["crush_ribs"] = False
|
||||
vars["chamfer_holes"] = False
|
||||
vars["printable_hole_top"] = True
|
||||
self.scad_runner.create_image([], Path('magnet_and_screw_holes_printable.png'))
|
||||
|
||||
def test_magnet_and_screw_holes_all(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["refined_holes"] = False
|
||||
vars["magnet_holes"] = True
|
||||
vars["screw_holes"] = True
|
||||
vars["crush_ribs"] = True
|
||||
vars["chamfer_holes"] = True
|
||||
vars["printable_hole_top"] = True
|
||||
self.scad_runner.create_image([], Path('magnet_and_screw_holes_all.png'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
78
tests/test_holes.py
Normal file
78
tests/test_holes.py
Normal file
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
Tests for gridfinity-rebuilt-holes.scad
|
||||
@Copyright Arthur Moore 2024 MIT License
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from openscad_runner import *
|
||||
import unittest
|
||||
|
||||
|
||||
class TestHoleCutouts(unittest.TestCase):
|
||||
"""
|
||||
Test Hole Cutouts. The negatives used with `difference()` to create a hole.
|
||||
|
||||
Currently only makes sure code runs, and outputs pictures for manual verification.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.scad_runner = OpenScadRunner(Path('../gridfinity-rebuilt-holes.scad'))
|
||||
self.scad_runner.image_folder_base = Path('../images/hole_cutouts/')
|
||||
self.scad_runner.camera_arguments = CameraArguments(Vec3(0,0,0), CameraRotations.AngledTop, 50)
|
||||
|
||||
def test_refined_hole(self):
|
||||
"""
|
||||
refined_hole() is special, since top_angle_camera is not appropriate for it.
|
||||
"""
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.AngledBottom)
|
||||
test_args = set_variable_argument('test_options',
|
||||
'bundle_hole_options(refined_hole=true, magnet_hole=false, screw_hole=false, crush_ribs=false, chamfer=false, supportless=false)')
|
||||
self.scad_runner.create_image(test_args, Path('refined_hole.png'))
|
||||
|
||||
def test_plain_magnet_hole(self):
|
||||
test_args = set_variable_argument('test_options',
|
||||
'bundle_hole_options(refined_hole=false, magnet_hole=true, screw_hole=false, crush_ribs=false, chamfer=false, supportless=false)')
|
||||
self.scad_runner.create_image(test_args, Path('magnet_hole.png'))
|
||||
|
||||
def test_plain_screw_hole(self):
|
||||
test_args = set_variable_argument('test_options',
|
||||
'bundle_hole_options(refined_hole=false, magnet_hole=false, screw_hole=true, crush_ribs=false, chamfer=false, supportless=false)')
|
||||
self.scad_runner.create_image(test_args, Path('screw_hole.png'))
|
||||
|
||||
def test_magnet_and_screw_hole(self):
|
||||
test_args = set_variable_argument('test_options',
|
||||
'bundle_hole_options(refined_hole=false, magnet_hole=true, screw_hole=true, crush_ribs=false, chamfer=false, supportless=false)')
|
||||
self.scad_runner.create_image(test_args, Path('magnet_and_screw_hole.png'))
|
||||
|
||||
def test_chamfered_magnet_hole(self):
|
||||
test_args = set_variable_argument('test_options',
|
||||
'bundle_hole_options(refined_hole=false, magnet_hole=true, screw_hole=false, crush_ribs=false, chamfer=true, supportless=false)')
|
||||
self.scad_runner.create_image(test_args, Path('chamfered_magnet_hole.png'))
|
||||
|
||||
def test_magnet_hole_crush_ribs(self):
|
||||
test_args = set_variable_argument('test_options',
|
||||
'bundle_hole_options(refined_hole=false, magnet_hole=true, screw_hole=false, crush_ribs=true, chamfer=false, supportless=false)')
|
||||
self.scad_runner.create_image(test_args, Path('magnet_hole_crush_ribs.png'))
|
||||
|
||||
def test_magnet_hole_supportless(self):
|
||||
test_args = set_variable_argument('test_options',
|
||||
'bundle_hole_options(refined_hole=false, magnet_hole=true, screw_hole=false, crush_ribs=false, chamfer=false, supportless=true)')
|
||||
self.scad_runner.create_image(test_args, Path('magnet_hole_supportless.png'))
|
||||
|
||||
def test_magnet_and_screw_hole_supportless(self):
|
||||
test_args = set_variable_argument('test_options',
|
||||
'bundle_hole_options(refined_hole=false, magnet_hole=true, screw_hole=true, crush_ribs=false, chamfer=false, supportless=true)')
|
||||
self.scad_runner.create_image(test_args, Path('magnet_and_screw_hole_supportless.png'))
|
||||
|
||||
def test_all_hole_options(self):
|
||||
test_args = set_variable_argument('test_options',
|
||||
'bundle_hole_options(refined_hole=false, magnet_hole=true, screw_hole=true, crush_ribs=true, chamfer=true, supportless=true)')
|
||||
self.scad_runner.create_image(test_args, Path('all_hole_options.png'))
|
||||
|
||||
def test_no_hole(self):
|
||||
test_args = set_variable_argument('test_options',
|
||||
'bundle_hole_options(refined_hole=false, magnet_hole=false, screw_hole=false, crush_ribs=true, chamfer=true, supportless=true)')
|
||||
self.scad_runner.create_image(test_args, Path('no_hole.png'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
50
tests/test_spiral_vase.py
Normal file
50
tests/test_spiral_vase.py
Normal file
@@ -0,0 +1,50 @@
|
||||
"""
|
||||
Tests for gridfinity-spiral-vase.scad
|
||||
@Copyright Arthur Moore 2024 MIT License
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
import json
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
from openscad_runner import *
|
||||
|
||||
class TestSpiralVaseBase(unittest.TestCase):
|
||||
"""
|
||||
Test creating a single base in "gridfinity-spiral-vase.scad"
|
||||
|
||||
Currently only makes sure code runs, and outputs pictures for manual verification.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
parameter_file_path = Path("gridfinity-spiral-vase.json")
|
||||
parameter_file_data = ParameterFile.from_json(parameter_file_path.read_text())
|
||||
cls.default_parameters = parameter_file_data.parameterSets["Default"]
|
||||
|
||||
def setUp(self):
|
||||
self.scad_runner = OpenScadRunner(Path('../gridfinity-spiral-vase.scad'))
|
||||
self.scad_runner.image_folder_base = Path('../images/spiral_vase_base/')
|
||||
self.scad_runner.parameters = self.default_parameters.copy()
|
||||
self.scad_runner.parameters["type"] = 1 # Create a Base
|
||||
self.scad_runner.camera_arguments = CameraArguments(Vec3(0,0,0), CameraRotations.AngledBottom, 150)
|
||||
|
||||
def test_no_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_holes"] = False
|
||||
self.scad_runner.create_image([], Path('no_holes_bottom.png'))
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.Top)
|
||||
self.scad_runner.create_image([], Path('no_holes_top.png'))
|
||||
|
||||
def test_refined_holes(self):
|
||||
vars = self.scad_runner.parameters
|
||||
vars["enable_holes"] = True
|
||||
self.scad_runner.create_image([], Path('with_holes_bottom.png'))
|
||||
self.scad_runner.camera_arguments = self.scad_runner.camera_arguments.with_rotation(CameraRotations.Top)
|
||||
self.scad_runner.create_image([], Path('with_holes_top.png'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user