Testing

Easy3D / Reference / Testing

Easy3D keeps a small test suite registered with CTest (EASY3D_BUILD_TESTS=ON by default). The interesting part is its two-tier design: CNA-free tests always build and run, while CNA-dependent tests run when CNA is linked — and are still compile-checked when it is not.

The test suite

CTest nameCoversRuns in default build?
basicsVersion info and other CNA-free helpersYes — CNA-free
texture_atlasTextureAtlas: named rects, AddGrid, UV math, throwing/non-throwing lookupsYes — CNA-free
cameraCamera3D, OrbitCamera, FollowCamera — executes real CNA matrix/vector mathNo — needs CNA linked
batchesBillboardBatch, CubeBatch, DebugDraw item storageNo — needs CNA linked
cube_meshAppendCubeMesh/BuildCubeMesh — vertex counts, index validity, face positions, UV corners, windingNo — needs CNA linked

Running the tests

Default build — 2 tests

cmake -S . -B build
cmake --build build
ctest --test-dir build          # basics, texture_atlas

CNA-linked build — full suite

cmake -S . -B build -DEASY3D_LINK_CNA=ON
cmake --build build
ctest --test-dir build          # basics, texture_atlas, camera, batches, cube_mesh

Why some tests need CNA linked

The camera, batch, and cube-mesh tests exercise CNA math at runtime — even just constructing Vector3/Vector2 values calls CNA's compiled constructors. So running them requires linking CNA. Compiling them does not: CNA's math types are declared in headers and only defined in CNA's .cpp files, so translating the test sources to object code needs only the headers.

The compile-check trick

In the default (no-CNA-link) build, the CNA-dependent test sources are still built as OBJECT libraries — compiled but never linked into an executable, so there are no undefined-symbol errors:

add_library(easy3d_test_camera_compilecheck    OBJECT test_camera.cpp)
add_library(easy3d_test_batches_compilecheck   OBJECT test_batches.cpp)
add_library(easy3d_test_cube_mesh_compilecheck OBJECT test_cube_mesh.cpp)

This is a cheap compile-only check that catches CNA header/API drift even in the light default build: if CNA renames a method or changes a signature, the default build breaks immediately instead of waiting for someone to run a CNA-linked build.

Test style

The tests are plain C++ programs with a tiny local CHECK macro — no test framework dependency. They print failures with file/line and return a non-zero exit code, which is all CTest needs:

#define CHECK(cond)                                               \
    do {                                                          \
        if (!(cond)) {                                            \
            std::printf("FAIL: %s (line %d)\n", #cond, __LINE__); \
            ++g_failures;                                         \
        }                                                         \
    } while (0)

This matches the project's "small, boring, testable" principle: when you add behavior that can be tested without linking all of CNA, you add or update a small test alongside it.