discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

C++ Unit testing for the OpenSCAD codebase

CC
Cory Cross
Wed, Oct 15, 2025 11:12 PM

I want to write a unit test for the function
calculateLineLineDistance(). It's got at least one bug.[0]

OrcaSlicer uses Catch2 framework. Any objections to adding that to
OpenSCAD tests?

  • Cory

[0] Measure the vertical line from the origin to the same line on the
upper cube: length==5. Move the upper cube +1X; the distance is now 4.12311.
cube(1);
translate([0,0,5]) cube(1);
then
cube(1);
translate([1,0,5]) cube(1);

I want to write a unit test for the function calculateLineLineDistance(). It's got at least one bug.[0] OrcaSlicer uses Catch2 framework. Any objections to adding that to OpenSCAD tests? - Cory [0] Measure the vertical line from the origin to the same line on the upper cube: length==5. Move the upper cube +1X; the distance is now 4.12311. cube(1); translate([0,0,5]) cube(1); then cube(1); translate([1,0,5]) cube(1);
MK
Marius Kintel
Wed, Oct 15, 2025 11:32 PM

I generally welcome unit tests. We haven’t prioritized this, partially because the internal components and APIs are a bit in flux.

Two things to think about:

  1. Evaluate the API before writing tests, to try to ensure that the API stays somewhat stable, and the API is designed for testability.
  2. The regression tests are designed to run decoupled from the build system (e.g. using an externally built OpenSCAD binary), so we may want unit tests to be separate from regression tests, e.g. in a separate folder with a separate CMake config.

I don’t have any strong opinions on test frameworks. Ideally it should work with CTest. I’ve really only used GoogleTest in the past.

-Marius

On Oct 15, 2025, at 19:12, Cory Cross via Discuss discuss@lists.openscad.org wrote:

I want to write a unit test for the function calculateLineLineDistance(). It's got at least one bug.[0]

OrcaSlicer uses Catch2 framework. Any objections to adding that to OpenSCAD tests?

  • Cory

[0] Measure the vertical line from the origin to the same line on the upper cube: length==5. Move the upper cube +1X; the distance is now 4.12311.
cube(1);
translate([0,0,5]) cube(1);
then
cube(1);
translate([1,0,5]) cube(1);


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

I generally welcome unit tests. We haven’t prioritized this, partially because the internal components and APIs are a bit in flux. Two things to think about: 1. Evaluate the API before writing tests, to try to ensure that the API stays somewhat stable, and the API is designed for testability. 2. The regression tests are designed to run decoupled from the build system (e.g. using an externally built OpenSCAD binary), so we may want unit tests to be separate from regression tests, e.g. in a separate folder with a separate CMake config. I don’t have any strong opinions on test frameworks. Ideally it should work with CTest. I’ve really only used GoogleTest in the past. -Marius > On Oct 15, 2025, at 19:12, Cory Cross via Discuss <discuss@lists.openscad.org> wrote: > > I want to write a unit test for the function calculateLineLineDistance(). It's got at least one bug.[0] > > OrcaSlicer uses Catch2 framework. Any objections to adding that to OpenSCAD tests? > > - Cory > > [0] Measure the vertical line from the origin to the same line on the upper cube: length==5. Move the upper cube +1X; the distance is now 4.12311. > cube(1); > translate([0,0,5]) cube(1); > then > cube(1); > translate([1,0,5]) cube(1); > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
CC
Cory Cross
Thu, Oct 16, 2025 3:18 AM

On 10/15/25 4:32 PM, Marius Kintel via Discuss wrote:

I generally welcome unit tests. We haven’t prioritized this, partially because the internal components and APIs are a bit in flux.

Two things to think about:

  1. Evaluate the API before writing tests, to try to ensure that the API stays somewhat stable, and the API is designed for testability.
  2. The regression tests are designed to run decoupled from the build system (e.g. using an externally built OpenSCAD binary), so we may want unit tests to be separate from regression tests, e.g. in a separate folder with a separate CMake config.

I don’t have any strong opinions on test frameworks. Ideally it should work with CTest. I’ve really only used GoogleTest in the past.

I'm writing something just to prove its fixed, so it felt bad to throw
it away after. It's certainly not the first time I've wanted to write
just a little bit of test, but no infra. Now I'm willing (I'm also
getting Orca's tests to run and block on GH).

Catch2 works with ctest. Good point on decoupled; easiest to not have
them under tests/ then. Will probably create unit_tests/ which will
contain a CMakeLists.txt and one cc file per subdirectory of src
(well, of the ones I'll write tests for... which is just utils for now).

-Cory

-Marius

On Oct 15, 2025, at 19:12, Cory Cross via Discuss discuss@lists.openscad.org wrote:

I want to write a unit test for the function calculateLineLineDistance(). It's got at least one bug.[0]

OrcaSlicer uses Catch2 framework. Any objections to adding that to OpenSCAD tests?

  • Cory

[0] Measure the vertical line from the origin to the same line on the upper cube: length==5. Move the upper cube +1X; the distance is now 4.12311.
cube(1);
translate([0,0,5]) cube(1);
then
cube(1);
translate([1,0,5]) cube(1);


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org


OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org

On 10/15/25 4:32 PM, Marius Kintel via Discuss wrote: > I generally welcome unit tests. We haven’t prioritized this, partially because the internal components and APIs are a bit in flux. > > Two things to think about: > 1. Evaluate the API before writing tests, to try to ensure that the API stays somewhat stable, and the API is designed for testability. > 2. The regression tests are designed to run decoupled from the build system (e.g. using an externally built OpenSCAD binary), so we may want unit tests to be separate from regression tests, e.g. in a separate folder with a separate CMake config. > > I don’t have any strong opinions on test frameworks. Ideally it should work with CTest. I’ve really only used GoogleTest in the past. I'm writing something just to prove its fixed, so it felt bad to throw it away after. It's certainly not the first time I've wanted to write just a little bit of test, but no infra. Now I'm willing (I'm also getting Orca's tests to run and block on GH). Catch2 works with ctest. Good point on decoupled; easiest to not have them under `tests/` then. Will probably create `unit_tests/` which will contain a CMakeLists.txt and one cc file per subdirectory of `src` (well, of the ones I'll write tests for... which is just `utils` for now). -Cory > > -Marius > >> On Oct 15, 2025, at 19:12, Cory Cross via Discuss <discuss@lists.openscad.org> wrote: >> >> I want to write a unit test for the function calculateLineLineDistance(). It's got at least one bug.[0] >> >> OrcaSlicer uses Catch2 framework. Any objections to adding that to OpenSCAD tests? >> >> - Cory >> >> [0] Measure the vertical line from the origin to the same line on the upper cube: length==5. Move the upper cube +1X; the distance is now 4.12311. >> cube(1); >> translate([0,0,5]) cube(1); >> then >> cube(1); >> translate([1,0,5]) cube(1); >> _______________________________________________ >> OpenSCAD mailing list >> To unsubscribe send an email to discuss-leave@lists.openscad.org > _______________________________________________ > OpenSCAD mailing list > To unsubscribe send an email to discuss-leave@lists.openscad.org
MK
Marius Kintel
Thu, Oct 16, 2025 3:23 AM

On Oct 15, 2025, at 23:18, Cory Cross openscad@corycross.org wrote:

Catch2 works with ctest. Good point on decoupled; easiest to not have them under tests/ then. Will probably create unit_tests/ which will contain a CMakeLists.txt and one cc file per subdirectory of src (well, of the ones I'll write tests for... which is just utils for now).

Yeah, or do tests/regression separate from just tests, but that can be hammered out later.
I also have a (currently weak) preference to put test code very close to the implementation, e.g. src/gui/Measurement_test.cc http://measurement_test.cc/ - or whereever the source ends up.

-Marius

> On Oct 15, 2025, at 23:18, Cory Cross <openscad@corycross.org> wrote: > > Catch2 works with ctest. Good point on decoupled; easiest to not have them under `tests/` then. Will probably create `unit_tests/` which will contain a CMakeLists.txt and one cc file per subdirectory of `src` (well, of the ones I'll write tests for... which is just `utils` for now). > Yeah, or do tests/regression separate from just tests, but that can be hammered out later. I also have a (currently weak) preference to put test code very close to the implementation, e.g. src/gui/Measurement_test.cc <http://measurement_test.cc/> - or whereever the source ends up. -Marius
CC
Cory Cross
Thu, Oct 16, 2025 3:53 AM

On 10/15/25 8:23 PM, Marius Kintel via Discuss wrote:

Yeah, or do tests/regression separate from just tests, but that can be
hammered out later.
I also have a (currently weak) preference to put test code very close
to the implementation, e.g. src/gui/Measurement_test.cc
http://measurement_test.cc - or whereever the source ends up.

I do too, but the LLM says it's advised against because the root
CMakeLists.txt commingles test and not-test stuff and the norm is to
keep tests under tests/. But I don't do a lot of C++, so I can't judge
the accuracy of that claim.

But, it says I can do it by adding something like this to the root
CMakeLists.txt:

if(ENABLE_TESTS)
  message(STATUS "Configuring OpenSCAD Unit Tests")

  file(GLOB_RECURSE TEST_SOURCES
    "src/*_test.cc"
  )

  add_executable(OpenSCADUnitTests ${TEST_SOURCES})

  target_link_libraries(OpenSCADUnitTests PRIVATE Catch2::Catch2 OpenSCAD)

  add_test(NAME OpenSCAD_Unit_Tests COMMAND OpenSCADUnitTests)
endif()

(Along with FetchContent in the beginning to obtain Catch2). If that
works for you, that's what I'll do.

  • Cory
On 10/15/25 8:23 PM, Marius Kintel via Discuss wrote: > Yeah, or do tests/regression separate from just tests, but that can be > hammered out later. > I also have a (currently weak) preference to put test code very close > to the implementation, e.g. src/gui/Measurement_test.cc > <http://measurement_test.cc> - or whereever the source ends up. I do too, but the LLM says it's advised against because the root CMakeLists.txt commingles test and not-test stuff and the norm is to keep tests under `tests/`. But I don't do a lot of C++, so I can't judge the accuracy of that claim. But, it says I can do it by adding something like this to the root CMakeLists.txt: if(ENABLE_TESTS)   message(STATUS "Configuring OpenSCAD Unit Tests")   file(GLOB_RECURSE TEST_SOURCES     "src/*_test.cc"   )   add_executable(OpenSCADUnitTests ${TEST_SOURCES})   target_link_libraries(OpenSCADUnitTests PRIVATE Catch2::Catch2 OpenSCAD)   add_test(NAME OpenSCAD_Unit_Tests COMMAND OpenSCADUnitTests) endif() (Along with FetchContent in the beginning to obtain Catch2). If that works for you, that's what I'll do. - Cory
MK
Marius Kintel
Thu, Oct 16, 2025 4:31 AM

On Oct 15, 2025, at 23:53, Cory Cross via Discuss discuss@lists.openscad.org wrote:

But, it says I can do it by adding something like this to the root CMakeLists.txt:

[…]
Yup, smth. Like that. We can discuss later whether globbing is good or not.

(Along with FetchContent in the beginning to obtain Catch2). If that works for you, that's what I'll do.

Please no FetchContent. It will break hermetic builds. Better find and link Catch2 using a CMake find macro.
As a temporary hack, you can submodule it.

-Marius

> On Oct 15, 2025, at 23:53, Cory Cross via Discuss <discuss@lists.openscad.org> wrote: > > But, it says I can do it by adding something like this to the root CMakeLists.txt: […] Yup, smth. Like that. We can discuss later whether globbing is good or not. > (Along with FetchContent in the beginning to obtain Catch2). If that works for you, that's what I'll do. > Please no FetchContent. It will break hermetic builds. Better find and link Catch2 using a CMake find macro. As a temporary hack, you can submodule it. -Marius
CC
Cory Cross
Thu, Oct 16, 2025 4:49 AM

On 10/15/25 9:31 PM, Marius Kintel via Discuss wrote:

Yup, smth. Like that. We can discuss later whether globbing is good or not.

Great!

(Along with FetchContent in the beginning to obtain Catch2). If that works for you, that's what I'll do.

Please no FetchContent. It will break hermetic builds. Better find and link Catch2 using a CMake find macro.
As a temporary hack, you can submodule it.

Ah, I think this means you want to use the system's Catch2? I can do
that. In the if(ENABLE_TESTS) block I'll have find_package(Catch2
REQUIRED). and update some scripts so the ubuntu CI image install it (I
only think the Linux build needs to run the unit tests?)

Thanks,
Cory

On 10/15/25 9:31 PM, Marius Kintel via Discuss wrote: > Yup, smth. Like that. We can discuss later whether globbing is good or not. Great! >> (Along with FetchContent in the beginning to obtain Catch2). If that works for you, that's what I'll do. >> > Please no FetchContent. It will break hermetic builds. Better find and link Catch2 using a CMake find macro. > As a temporary hack, you can submodule it. Ah, I think this means you want to use the system's Catch2? I can do that. In the if(ENABLE_TESTS) block I'll have find_package(Catch2 REQUIRED). and update some scripts so the ubuntu CI image install it (I only think the Linux build needs to run the unit tests?) Thanks, Cory
MK
Marius Kintel
Thu, Oct 16, 2025 2:32 PM

On Oct 16, 2025, at 00:49, Cory Cross via Discuss discuss@lists.openscad.org wrote:

Ah, I think this means you want to use the system's Catch2? I can do that. In the if(ENABLE_TESTS) block I'll have find_package(Catch2 REQUIRED). and update some scripts so the ubuntu CI image install it (I only think the Linux build needs to run the unit tests?)

We should enable this on all platforms, but prototyping it as Linux-first is fine.

-Marius

On Oct 16, 2025, at 00:49, Cory Cross via Discuss <discuss@lists.openscad.org> wrote: > > Ah, I think this means you want to use the system's Catch2? I can do that. In the if(ENABLE_TESTS) block I'll have find_package(Catch2 REQUIRED). and update some scripts so the ubuntu CI image install it (I only think the Linux build needs to run the unit tests?) > We should enable this on all platforms, but prototyping it as Linux-first is fine. -Marius
CC
Cory Cross
Sun, Oct 19, 2025 3:37 PM

To add unit tests, I have to link against all the same libraries.
Currently we just declare the binary output and add all the library,
compile, and linker information to it directly, which then cannot be
used for the unit tests.

The ways I've seen to work on this is:

  1. Repeat every line which adds a library and settings (i.e. C17 or C20)
    to also add it to the unit test binary.
  2. Have most everything stay the same except remove int main to a
    shim; so create a static library with all of openscad; have both shim
    binary and unit test library link to it
  3. Link unit tests into binary and have a flag switch to Catch2 when
    given a particular flag

I've gone with approach #2 so far; only problem has been the resources
are missing. Please LMK if this approach is unacceptable. See
https://github.com/openscad/openscad/pull/6299

  • Cory
To add unit tests, I have to link against all the same libraries. Currently we just declare the binary output and add all the library, compile, and linker information to it directly, which then cannot be used for the unit tests. The ways I've seen to work on this is: 1. Repeat every line which adds a library and settings (i.e. C17 or C20) to also add it to the unit test binary. 2. Have most everything stay the same except remove `int main` to a shim; so create a static library with all of openscad; have both shim binary and unit test library link to it 3. Link unit tests into binary and have a flag switch to Catch2 when given a particular flag I've gone with approach #2 so far; only problem has been the resources are missing. Please LMK if this approach is unacceptable. See https://github.com/openscad/openscad/pull/6299 - Cory
MK
Marius Kintel
Sun, Oct 19, 2025 6:45 PM

From here, the technical discussion is probably better held on GitHub.

On Oct 19, 2025, at 11:37, Cory Cross openscad@corycross.org wrote:

To add unit tests, I have to link against all the same libraries. Currently we just declare the binary output and add all the library, compile, and linker information to it directly, which then cannot be used for the unit tests.

The ways I've seen to work on this is:

  1. Repeat every line which adds a library and settings (i.e. C17 or C20) to also add it to the unit test binary.
  2. Have most everything stay the same except remove int main to a shim; so create a static library with all of openscad; have both shim binary and unit test library link to it
  3. Link unit tests into binary and have a flag switch to Catch2 when given a particular flag

I've gone with approach #2 so far; only problem has been the resources are missing. Please LMK if this approach is unacceptable. See https://github.com/openscad/openscad/pull/6299

  • Cory
From here, the technical discussion is probably better held on GitHub. > On Oct 19, 2025, at 11:37, Cory Cross <openscad@corycross.org> wrote: > > To add unit tests, I have to link against all the same libraries. Currently we just declare the binary output and add all the library, compile, and linker information to it directly, which then cannot be used for the unit tests. > > The ways I've seen to work on this is: > > 1. Repeat every line which adds a library and settings (i.e. C17 or C20) to also add it to the unit test binary. > 2. Have most everything stay the same except remove `int main` to a shim; so create a static library with all of openscad; have both shim binary and unit test library link to it > 3. Link unit tests into binary and have a flag switch to Catch2 when given a particular flag > > I've gone with approach #2 so far; only problem has been the resources are missing. Please LMK if this approach is unacceptable. See https://github.com/openscad/openscad/pull/6299 > > - Cory