Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Once you're up and running consider the following reference material.

**Fine tuning:**
* [Supplying your own main()](own-main.md#top)
* [Tests inside a library project](library-tests.md#top)
* [Compile-time configuration](configuration.md#top)
* [String Conversions](tostring.md#top)

Expand Down
4 changes: 4 additions & 0 deletions docs/cmake-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
Because we use CMake to build Catch2, we also provide a couple of
integration points for our users.

If you ship tests with a library across multiple `.cpp` files, see
[Tests inside a library project](library-tests.md#top) so every
`TEST_CASE` is linked into the same test executable.

1) Catch2 exports a (namespaced) CMake target
2) Catch2's repository contains CMake scripts for automatic registration
of `TEST_CASE`s in CTest
Expand Down
12 changes: 12 additions & 0 deletions docs/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
[Why cannot I derive from the built-in reporters?](#why-cannot-i-derive-from-the-built-in-reporters)<br>
[What is Catch2's ABI stability policy?](#what-is-catch2s-abi-stability-policy)<br>
[What is Catch2's API stability policy?](#what-is-catch2s-api-stability-policy)<br>
[How do I run tests that live in my library's source tree?](#how-do-i-run-tests-that-live-in-my-librarys-source-tree)<br>
[Does Catch2 support running tests in parallel?](#does-catch2-support-running-tests-in-parallel)<br>
[Can I compile Catch2 into a dynamic library?](#can-i-compile-catch2-into-a-dynamic-library)<br>
[What repeatability guarantees does Catch2 provide?](#what-repeatability-guarantees-does-catch2-provide)<br>
Expand Down Expand Up @@ -51,6 +52,17 @@ This means that we will not knowingly make backwards-incompatible changes
without incrementing the major version number.


## How do I run tests that live in my library's source tree?

Put every translation unit that defines `TEST_CASE`s into **one** test
executable and link it with `Catch2::Catch2WithMain` (or a single custom
`main` plus `Catch2::Catch2`). Do not rely on tests compiled only into a
static library unless you know they are pulled into the runner's link.

See [Tests inside a library project](library-tests.md#top) for a CMake
example and common pitfalls.


## Does Catch2 support running tests in parallel?

Not natively, no. We see running tests in parallel as the job of an
Expand Down
96 changes: 96 additions & 0 deletions docs/library-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<a id="top"></a>
# Tests inside a library project

Catch2 discovers `TEST_CASE`s at static initialization time in every
translation unit that is **linked into the test executable**. If you
ship tests with a library (several `.cpp` files, each with its own
`TEST_CASE`s), they will not run unless all of those object files end up
in the same binary you execute.

This page summarizes the layout that avoids “missing” tests when using
multiple compilation units. It replaces older v2 guidance around
`CATCH_CONFIG_RUNNER`; in v3 use [`Catch::Session`](own-main.md#top)
instead (see also [Migrating from v2 to v3](migrate-v2-to-v3.md#top)).


## Recommended layout

```
mylib/
include/
src/
tests/
test_foo.cpp
test_bar.cpp
CMakeLists.txt
```

Keep test sources under `tests/` (or similar) and link them into **one**
test executable together with your library.


## CMake (recommended)

```cmake
add_library(mylib ...)

file(GLOB MYLIB_TEST_SOURCES CONFIGURE_DEPENDS tests/*.cpp)
# If you provide a custom main, exclude it from the glob and add it explicitly.
list(FILTER MYLIB_TEST_SOURCES EXCLUDE REGEX "test_main\\.cpp$")

add_executable(mylib-tests ${MYLIB_TEST_SOURCES})
target_link_libraries(mylib-tests PRIVATE mylib Catch2::Catch2WithMain)

include(CTest)
include(Catch)
catch_discover_tests(mylib-tests)
```

`Catch2::Catch2WithMain` supplies a single `main` for the executable.
Register tests with [`catch_discover_tests`](cmake-integration.md#catch_discover_tests)
so CTest sees each `TEST_CASE`.

**Common mistake:** compiling test `.cpp` files into the `mylib` static
library but linking only `mylib` into a tiny runner that has no test
sources of its own. The test object files are then not linked into the
runner and Catch2 never sees them. Prefer linking test sources directly
into `mylib-tests`, or ensure the static library is linked with flags
that pull in all object files (for example `--whole-archive` on GCC/Clang).


## Custom `main`

If you need code to run before or after the test session, provide your
own `main` and link only `Catch2::Catch2`:

```cpp
#include <catch2/catch_session.hpp>

int main(int argc, char* argv[]) {
// Optional library-wide setup
const int result = Catch::Session().run(argc, argv);
// Optional library-wide teardown
return result;
}
```

There must be exactly **one** `main` in the test executable. See
[Supplying main() yourself](own-main.md#top) for more recipes.


## Without CMake

Compile every `.cpp` that defines `TEST_CASE`s into the same final
executable. If tests disappear after a refactor, check that each test
translation unit is still on the link line of the binary you run.


## Further reading

- [Getting Catch to work across multiple compilation units](https://groups.google.com/g/catch-forum/c/pQchmF6Pr0E) (Catch forum)
- [CATCH_CONFIG_RUNNER usage](https://groups.google.com/g/catch-forum/c/FV0Qo62DvgY) (Catch2 v2; use `Catch::Session` in v3)


---

[Home](Readme.md#top)