Skip to content

C++20 testing framework extension for compile-time expressions. Compatible with GTest, Catch2, Doctest and Boost.Test

License

Notifications You must be signed in to change notification settings

Teskann/constest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🧪 ConsTest

Test Clang Test GCC Test MSVC Test Framework Versions C++ Versions

C++20 library that allows you to test your code at compile time. It's an extension of popular testing frameworks.

TEST_CASE("Example test case")
{
    CONSTEXPR_SECTION("My compile-time test")
    {
        std::vector vec = {1, 3};
        CONSTEXPR_REQUIRE(vec[0] == 1);
        CONSTEXPR_REQUIRE(vec[0] + vec[1] == 5); // ❌ compilation error
    };
}

Works seamlessly with:

Google Test 👉 Example 📃 Documentation
Catch2 👉 Example 📃 Documentation
Doctest 👉 Example 📃 Documentation
Boost.Test 👉 Example 📃 Documentation

ConsTest was initially a contribution of mine to Catch2, but the PR was not merged. So I decided to make it better using C++20 features (Catch2 requires C++17) and to make it compatible with other popular testing frameworks.

✨ Why ConsTest?

Lately, C++ has been criticized for its lack of memory safety.

Testing at compile time is the only way to guarantee your code doesn't lead to memory corruption issues. This is critical for writing safe libraries and software programs.

With ConsTest, you can:

  • ✅ Test constexpr functions at compile time
  • ✅ Guarantee absence of undefined behavior and erroneous behavior in your tested code
  • ✅ Ensure your code is free from memory leaks

🎯 Features

Catch failures at compile-time

// Catch2 example
TEST_CASE("Example test case")
{
    CONSTEXPR_SECTION("Addition")
    {
        CONSTEXPR_REQUIRE(1 + 1 == 2);
        CONSTEXPR_REQUIRE(2 + 2 == 5); // ❌ compilation error
    };
}

Test transient expressions at compile time

// GTest example
TEST(example_tests, non_transient_constexpr_evaluation)
{
    CONSTEXPR_SECTION("std::sort and std::find")
    {
        std::vector vec = {5, 2, 8, 1, 9};
        std::ranges::sort(vec);

        CONSTEXPR_EXPECT_EQ(vec[0], 1);
        CONSTEXPR_EXPECT_EQ(vec[4], 9);

        auto it = std::ranges::find(vec, 8);
        CONSTEXPR_ASSERT_TRUE(it != vec.end());
    };
}

Catch Undefined Behaviors at compile time

// GTest example
TEST(example_tests, various_undefined_behavior) {
    CONSTEXPR_SECTION("Out of bounds") {
        std::vector vec = {1, 2, 3};
        CONSTEXPR_EXPECT_EQ(vec[3], 3); // ❌ compilation error
    };
        
    CONSTEXPR_SECTION("Double delete")
    {
        auto* const a = new int{ 10 };
        delete a;
        delete a; // ❌ compilation error
    };

    CONSTEXPR_SECTION("Use after free")
    {
        auto* const a = new int{ 10 };
        delete a;
        auto b = *a + 1; // ❌ compilation error
    };
}

Warning

Note that some compilers may have bugs that allow code with undefined behavior to compile successfully in constant evaluated contexts, even though it violates the C++ standard.

Catch memory leaks at compile time

// GTest example
TEST(example_tests, memory_leaks)
{
    CONSTEXPR_SECTION("new, no delete")
    {
        auto* const a = new int{ 10 }; // ❌ compilation error 
    };
}

Seamless Integration with your favorite testing framework

Wrap your tests in CONSTEXPR_SECTION macros to ensure they are executed at compile time. Prefix assertion macros from your testing framework with CONSTEXPR_ to enable compile-time assertions.

Refer to the documentation of your testing framework for more information:

CONSTEXPR_SECTIONs are also evaluated at runtime

So that it does not break your code coverage.

This is also important because a call to a constexpr function might give different results at runtime.


📋 Prerequisites

What you can test in ConsTest depends on your compiler and the C++ standard version you use.

📦 Get ConsTest

Using CPM (CMake Package Manager)

CPMAddPackage("gh:teskann/constest@1.0.0")
target_link_libraries(your_target PRIVATE constest)

# Configure ConsTest for your testing framework
target_compile_definitions(your_target PRIVATE CONSTEST_CONFIG_XXX)

🤝 Contributing

Contributions are welcome. Whether it's bug reports, feature requests, or pull requests.

About

C++20 testing framework extension for compile-time expressions. Compatible with GTest, Catch2, Doctest and Boost.Test

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published