Use this guide when adding or changing tests. The checked-out source is authoritative:
test/main.h configures and runs the test framework and aggregates the shared helpers.test/numerical_test_helpers.h defines numerical comparison, assertion, and tolerance helpers.test/product_test_helpers.h defines matrix-product error bounds.test/random_matrix_helper.h and test/type_test_helpers.h define random-matrix and type utilities.cmake/EigenTesting.cmake defines test registration and splitting.test/CMakeLists.txt and contrib/test/CMakeLists.txt register the suites.cmake/EigenConfigureTesting.cmake defines aggregate build and check targets.Configure a dedicated build directory. Unit tests are excluded from CMake's default all target, although a bare build may still build enabled auxiliary libraries.
cmake -G Ninja -S . -B build cmake --build build --target buildtests ctest --test-dir build --parallel --output-on-failure --no-tests=error
Useful aggregate targets are BuildOfficial, BuildContrib, buildsmoketests, buildtests_gpu, check, and check_gpu. Build and run one test explicitly when possible:
cmake --build build --target bdcsvd_3 ctest --test-dir build -R '^bdcsvd_3$' --output-on-failure --no-tests=error
Run the generated wrappers from the build directory because they invoke the configured build tool relative to their working directory:
cd build ./buildtests.sh <regex> ./check.sh <regex>
They filter registered parent names such as bdcsvd, not generated part names such as bdcsvd_3; use the explicit target recipe for one part.
Use a separate build directory for each materially different configuration. Do not rewrite one cache and describe the result as a second test run.
cmake -G Ninja -S . -B build-row-major -DEIGEN_DEFAULT_TO_ROW_MAJOR=ON cmake -G Ninja -S . -B build-no-vector -DEIGEN_TEST_NO_EXPLICIT_VECTORIZATION=ON
Consult the top-level CMakeLists.txt and nearby test CMake files for current options instead of copying an option inventory into documentation.
Eigen currently uses its own framework, not GoogleTest:
test/<name>.cpp or contrib/test/<name>.cpp.main.h, then the public umbrella header for tests of public behavior. A focused test of a private utility may include its implementation header only when that matches an established nearby pattern; never present such a path as a user include.VERIFY, VERIFY_IS_EQUAL, VERIFY_IS_APPROX, and the other helpers exposed through test/main.h.EIGEN_DECLARE_TEST(<name>) { ... }.ei_add_test(<name>) in the matching CMakeLists.txt, then reconfigure.Keep test/main.h limited to framework configuration, registration, shared-helper aggregation, and the test driver. Put reusable utilities in a narrowly named helper header; include it from main.h only when most tests need it.
For compile-failure coverage, use the established failtest/ pattern. Its _ok target must compile and its _ko target must fail with EIGEN_SHOULD_FAIL_TO_BUILD defined. _ko is a WILL_FAIL test whose action is a build, so it cannot tell the intended compile error from any other build failure: keep the construct narrow, and leave the RESOURCE_LOCK that ei_add_failtest uses to serialize the suite in place.
ei_add_test scans the source for CALL_SUBTEST_N, EIGEN_TEST_PART_N, and EIGEN_SUFFIXES;... markers.
EIGEN_SPLIT_LARGE_TESTS=ON, every discovered suffix becomes an executable <name>_<N> compiled with EIGEN_TEST_PART_<N>=1; the parent <name> target builds all parts.EIGEN_SUFFIXES;... supplies an explicit suffix list when ordinary source scanning cannot see macro-generated or conditional parts.CALL_SUBTEST_N or EIGEN_SUFFIXES fold into one <name> executable compiled with EIGEN_TEST_PART_ALL=1.EIGEN_TEST_PART_N marker forces splitting even when the option is off. If any such marker is present, all suffixes discovered in that source are emitted.ctest -R '^<name>$' does not match split parts. Use ctest -R '<name>' for every part or anchor one generated name.
After changing subtest registration, reconfigure and read back the generated target list. Two failure modes are silent: a subtest function whose CALL_SUBTEST call was dropped still compiles and looks like coverage, and a part reached only through a dispatch macro is not built under EIGEN_SPLIT_LARGE_TESTS=ON unless an EIGEN_SUFFIXES marker lists it.
A test that passes when the change is reverted is not coverage. Establish that it fails at the parent commit, or when that is impractical, that it reaches the new code by construction.
STATIC_CHECK on the flag or trait where one exists, in both directions: a type that must opt in and one that must stay out.test/buildsystem holds the coverage for Eigen‘s own CMake surface: what an install tree contains, what find_package(Eigen3) and the version ranges in cmake/Eigen3ConfigVersion.cmake.in accept, and how an embedding project opts out of Eigen’s install rules. They exist because those are claims doc/TopicCMakeGuide.dox makes to users and nothing else checks; the blocking documentation job only builds the docs, it does not run what they describe.
Not every scenario answers to the documentation. A find module that has to survive a second configure of the same build tree, or the wiring that routes a compiler launcher into a test's compile command, is CMake behavior nothing else exercises either.
cmake -G Ninja -S . -B build -DEIGEN_BUILD_TESTING=ON cmake -E chdir build ctest -L buildsystem --output-on-failure --no-tests=error
--no-tests=error belongs on every ctest invocation in this guide because CTest otherwise exits 0 when nothing matched: an anchored -R '^name$' against a split test, a mistyped name, or --test-dir under CMake 3.17 to 3.19, which predate that option, ignore it, and inspect the source directory instead. cmake -E chdir is the spelling that also works there.
No target needs building first: each scenario runs its own nested configure, build, and install into the CTest binary directory. Add a claim by dropping a scenario in scenarios/ and naming it in the list in test/buildsystem/CMakeLists.txt; the driver run_scenario.cmake supplies the assertion helpers.
Two hazards specific to these tests. Eigen calls export(PACKAGE Eigen3), so CMake's user package registry names every Eigen build tree on the machine — a find_package scenario must disable both registries and assert the package came from the prefix it installed, or it passes without reading that prefix at all. And because CMake registers the tests, a guard that stops matching yields an empty selection rather than a failure, so the CI job runs ctest with --no-tests=error.
EIGEN_NO_DEBUG code path: test/main.h undefines NDEBUG, and Macros.h derives EIGEN_NO_DEBUG from it. (HIP/SYCL device compilation and an explicit -DEIGEN_NO_DEBUG define it independently.) Behavior that depends on the macro needs a dedicated -DEIGEN_NO_DEBUG test target or a standalone -DNDEBUG check. Conversely, an eigen_assert body is only type-checked where assertions are enabled, so it can call members its argument type does not have and still compile in every release build.EIGEN_DEFAULT_TO_ROW_MAJOR build when layout is in play, and pin the layout explicitly where a test aliases one object's storage through a view whose default layout is fixed.EIGEN_TEST_NO_EXPLICIT_VECTORIZATION, EIGEN_UNALIGNED_VECTORIZE=0, or a narrower EIGEN_DEFAULT_DENSE_INDEX_TYPE when the change reasons about packets, alignment, or index width.CMAKE_BUILD_TYPE defaults to Release) and no CI job builds Debug, so a static constexpr class-template member that is odr-used without its C++14 namespace-scope definition links everywhere CI looks and fails only at -O0; see conventions.md. Build one Debug tree when adding such constants.test/CMakeLists.txt. The smoke list includes packetmath_fastmath, packetmath_fastmath_generic_16 where vector extensions are available, and parts of fastmath, bdcsvd_fastmath, and stable_norm_fastmath; these compile with -ffast-math where supported. Ordinary packetmath uses Eigen's EIGEN_FAST_MATH=1 approximation switch, which does not enable the compiler flag. Add focused coverage when a changed path falls outside the existing fast-math tests; numerics.md records the special-value hazards.VERIFY_IS_APPROX is a convenient broad comparison, not a machine-epsilon guarantee. test_precision<T>() uses NumTraits<T>::dummy_precision() generically and currently specializes float to 1e-3 and double/long double to 1e-6. Do not use it alone to claim ULP accuracy, backward stability, or IEEE special-value conformance.
For numerical kernels, add explicit named bounds based on epsilon, dimension, conditioning, or a backward-error model as appropriate. Check NaN, infinity, and signed zero explicitly when their distinction matters. Follow numerics.md for solver, packet, and scalar-math coverage.
Write such a bound as factor * NumTraits<RealScalar>::epsilon() at the site, and explain factor by its error model. Do not introduce tolerance wrapper helpers: the raw form is the established idiom across test/ and contrib/test/, and it is the computation, so a bound like 10 * n * eps * A.norm() stays readable as one. A bare decimal literal is worse than opaque — 1e-9 demands impossible accuracy from a float instantiation.
Two ways a comparison silently accepts everything, both of which have shipped here: a tolerance computed by the operation under test (a bound formed as (A.cwiseAbs() * B.cwiseAbs()) goes through the product code being tested — accumulate it independently instead), and a comparison that admits non-finite values (error <= tolerance holds for two infinities, and if (error > bound) never fires for a NaN error — assert the negation and reject a non-finite tolerance).
Run reproducible failures directly with a fixed seed and repeat count:
EIGEN_REPEAT=10 EIGEN_SEED=1 build/test/foo_3 build/test/foo_3 r10 s1
EIGEN_TEST_EXTERNAL_BLAS=ON finds a system BLAS, defines EIGEN_USE_BLAS, and links that BLAS into applicable official tests. With it off, ordinary tests exercise Eigen‘s normal implementation; they do not transparently use the in-tree eigen_blas library. EIGEN_BUILD_BLAS and EIGEN_BUILD_LAPACK separately build Eigen’s ABI shim libraries, which are also used to satisfy some optional sparse-backend links. There is currently no EIGEN_TEST_EXTERNAL_LAPACK option.
Report the exact targets, CTest regexes, configurations, compiler, and seeds run. Also report relevant hardware or optional backends that were unavailable locally.