Over time, some limitations of Catch2 emerged. Some of these are due to implementation details that cannot be easily changed, some of these are due to lack of development resources on our part, and some of these are due to plain old 3rd party bugs.
If you are using SECTION
s inside loops, you have to
create them with different name per loop’s iteration. The recommended
way to do so is to incorporate the loop’s counter into section’s name,
like so:
( "Looped section" ) {
TEST_CASEfor (char i = '0'; i < '5'; ++i) {
(std::string("Looped section ") + i) {
SECTION( "Everything is OK" );
SUCCEED}
}
}
or with a DYNAMIC_SECTION
macro (that was made for
exactly this purpose):
( "Looped section" ) {
TEST_CASEfor (char i = '0'; i < '5'; ++i) {
( "Looped section " << i) {
DYNAMIC_SECTION( "Everything is OK" );
SUCCEED}
}
}
If the last section in a test fails, it might be run again. This is
because Catch2 discovers SECTION
s dynamically, as they are
about to run, and if the last section in test case is aborted during
execution (e.g. via the REQUIRE
family of macros), Catch2
does not know that there are no more sections in that test case and must
run the test case again.
Compiling Catch2 with MinGW can be exceedingly slow, especially
during the linking step. As far as we can tell, this is caused by
deficiencies in its default linker. If you can tell MinGW to instead use
lld, via -fuse-ld=lld
, the link time should drop down to
reasonable length again.
This section outlines some missing features, what is their status and their possible workarounds.
Catch2’s assertion macros are not thread safe. This does not mean that you cannot use threads inside Catch’s test, but that only single thread can interact with Catch’s assertions and other macros.
This means that this is ok
std::vector<std::thread> threads;
std::atomic<int> cnt{ 0 };
for (int i = 0; i < 4; ++i) {
.emplace_back([&]() {
threads++cnt; ++cnt; ++cnt; ++cnt;
});
}
for (auto& t : threads) { t.join(); }
(cnt == 16); REQUIRE
because only one thread passes the REQUIRE
macro and
this is not
std::vector<std::thread> threads;
std::atomic<int> cnt{ 0 };
for (int i = 0; i < 4; ++i) {
.emplace_back([&]() {
threads++cnt; ++cnt; ++cnt; ++cnt;
(cnt == 16);
CHECK});
}
for (auto& t : threads) { t.join(); }
(cnt == 16); REQUIRE
We currently do not plan to support thread-safe assertions.
Catch does not support running tests in isolated (forked) processes. While this might in the future, the fact that Windows does not support forking and only allows full-on process creation and the desire to keep code as similar as possible across platforms, mean that this is likely to take significant development time, that is not currently available.
Catch2 keeps test execution in one process strictly serial, and there are no plans to change this. If you find yourself with a test suite that takes too long to run and you want to make it parallel, you have to run multiple processes side by side.
There are 2 basic ways to do that, * you can split your tests into multiple binaries, and run those binaries in parallel * you can run the same test binary multiple times, but run a different subset of the tests in each process
There are multiple ways to achieve the latter, the easiest way is to use test sharding.
This section outlines known bugs in 3rd party components (this means compilers, standard libraries, standard runtimes).
There is a known bug in Visual Studio 2017 (VC 15), that causes
compilation error when preprocessor attempts to stringize a raw string
literal (#
preprocessor directive is applied to it). This
snippet is sufficient to trigger the compilation error:
#include <catch2/catch_test_macros.hpp>
("test") {
TEST_CASE(std::string(R"("\)") == "\"\\");
CHECK}
Catch2 provides a workaround, by letting the user disable
stringification of the original expression by defining
CATCH_CONFIG_DISABLE_STRINGIFICATION
, like so:
#define CATCH_CONFIG_DISABLE_STRINGIFICATION
#include <catch2/catch_test_macros.hpp>
("test") {
TEST_CASE(std::string(R"("\)") == "\"\\");
CHECK}
Do note that this changes the output:
catchwork\test1.cpp(6):
PASSED:
CHECK( Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION )
with expansion:
""\" == ""\"
Some versions of libc++
and libstdc++
(or
their runtimes) have a bug with std::uncaught_exception()
getting stuck returning true
after rethrow, even if there
are no active exceptions. One such case is this snippet, which skipped
the sections “a” and “b”, when compiled against libcxxrt
from the master branch
#include <catch2/catch_test_macros.hpp>
("a") {
TEST_CASE(throw 3);
CHECK_THROWS}
("b") {
TEST_CASEint i = 0;
("a") { i = 1; }
SECTION("b") { i = 2; }
SECTION(i > 0);
CHECK}
If you are seeing a problem like this, i.e. weird test paths that
trigger only under Clang with libc++
, or only under very
specific version of libstdc++
, it is very likely you are
seeing this. The only known workaround is to use a fixed version of your
standard library.
The C++
standard requires that std::foo_ordering
is only comparable
with a literal 0. There are multiple strategies a stdlib
implementation can take to achieve this, and MSVC’s STL has changed the
strategy they use between two releases of VS 2022.
With the new strategy, REQUIRE((a <=> b) == 0)
no
longer compiles under MSVC. Note that Catch2 can compile code using MSVC
STL’s new strategy, but only when compiled with a C++20 conforming
compiler. MSVC is currently not conformant enough, but
clang-cl
will compile the assertion above using MSVC STL
without problem.
This change got in with MSVC v19.37](https://godbolt.org/z/KG9obzdvE).