diff --git a/docs/Readme.md b/docs/Readme.md index be7d1cd1..07968403 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -20,7 +20,10 @@ Fine tuning: Running: * [Command line](command-line.md#top) -* [CI and Build system integration](build-systems.md#top) + +Odds and ends: +* [CMake integration](cmake-integration.md#top) +* [CI and other miscellaneous pieces](ci-and-misc.md#top) FAQ: * [Why are my tests slow to compile?](slow-compiles.md#top) diff --git a/docs/build-systems.md b/docs/ci-and-misc.md similarity index 59% rename from docs/build-systems.md rename to docs/ci-and-misc.md index 2873bc62..97d5c839 100644 --- a/docs/build-systems.md +++ b/docs/ci-and-misc.md @@ -1,6 +1,7 @@ -# CI and build system integration +# CI and other odd pieces +This page talks about how Catch integrates with Continuous Integration Build Systems may refer to low-level tools, like CMake, or larger systems that run on servers, like Jenkins or TeamCity. This page will talk about both. ## Continuous Integration systems @@ -71,105 +72,31 @@ Catch offers prototypal support for being included in precompiled headers, but b * include "catch.hpp" again -### CMake - -In general we recommend "vendoring" Catch's single-include releases inside your own repository. If you do this, the following example shows a minimal CMake project: -```CMake -cmake_minimum_required(VERSION 3.0) - -project(cmake_test) - -# Prepare "Catch" library for other executables -set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/catch) -add_library(Catch INTERFACE) -target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR}) - -# Make test executable -set(TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) -add_executable(tests ${TEST_SOURCES}) -target_link_libraries(tests Catch) -``` -Note that it assumes that the path to the Catch's header is `catch/catch.hpp` from the `CMakeLists.txt` file. - - -You can also use the following CMake snippet to automatically fetch the entire Catch repository from github and configure it as an external project: -```CMake -cmake_minimum_required(VERSION 2.8.8) -project(catch_builder CXX) -include(ExternalProject) -find_package(Git REQUIRED) - -ExternalProject_Add( - catch - PREFIX ${CMAKE_BINARY_DIR}/catch - GIT_REPOSITORY https://github.com/philsquared/Catch.git - TIMEOUT 10 - UPDATE_COMMAND ${GIT_EXECUTABLE} pull - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - LOG_DOWNLOAD ON - ) - -# Expose required variable (CATCH_INCLUDE_DIR) to parent scope -ExternalProject_Get_Property(catch source_dir) -set(CATCH_INCLUDE_DIR ${source_dir}/single_include CACHE INTERNAL "Path to include folder for Catch") -``` - -If you put it in, e.g., `${PROJECT_SRC_DIR}/${EXT_PROJECTS_DIR}/catch/`, you can use it in your project by adding the following to your root CMake file: - -```CMake -# Includes Catch in the project: -add_subdirectory(${EXT_PROJECTS_DIR}/catch) -include_directories(${CATCH_INCLUDE_DIR} ${COMMON_INCLUDES}) -enable_testing(true) # Enables unit-testing. -``` - -The advantage of this approach is that you can always automatically update Catch to the latest release. The disadvantage is that it means bringing in lot more than you need. - - -### Automatic test registration -We provide 2 CMake scripts that can automatically register Catch-based -tests with CTest, - * `contrib/ParseAndAddCatchTests.cmake` - * `contrib/CatchAddTests.cmake` - -The first is based on parsing the test implementation files, and attempts -to register all `TEST_CASE`s using their tags as labels. This means that -these: - -```cpp -TEST_CASE("Test1", "[unit]") { - int a = 1; - int b = 2; - REQUIRE(a == b); -} - -TEST_CASE("Test2") { - int a = 1; - int b = 2; - REQUIRE(a == b); -} - -TEST_CASE("Test3", "[a][b][c]") { - int a = 1; - int b = 2; - REQUIRE(a == b); -} -``` -would be registered as 3 tests, `Test1`, `Test2` and `Test3`, -and 4 CTest labels would be created, `a`, `b`, `c` and `unit`. - - -The second is based on parsing the output of a Catch binary given -`--list-test-names-only`. This means that it deals with inactive -(e.g. commented-out) tests better, but requires CMake 3.10 for full -functionality. - ### CodeCoverage module (GCOV, LCOV...) If you are using GCOV tool to get testing coverage of your code, and are not sure how to integrate it with CMake and Catch, there should be an external example over at https://github.com/fkromer/catch_cmake_coverage + +### pkg-config + +Catch2 provides a rudimentary pkg-config integration, by registering itself +under the name `catch2`. This means that after Catch2 is installed, you +can use `pkg-config` to get its include path: `pkg-config --cflags catch2`. + +### gdb and lldb scripts + +Catch2's `contrib` folder also contains two simple debugger scripts, +`gdbinit` for `gdb` and `lldbinit` for `lldb`. If loaded into their +respective debugger, these will tell it to step over Catch2's internals +when stepping through code. + + +## CMake + +[As it has been getting kinda long, the documentation of Catch2's +integration with CMake has been moved to its own page.](cmake-integration.md#top) + + --- [Home](Readme.md#top) diff --git a/docs/cmake-integration.md b/docs/cmake-integration.md new file mode 100644 index 00000000..7120d163 --- /dev/null +++ b/docs/cmake-integration.md @@ -0,0 +1,185 @@ + +# CMake integration + +Because we use CMake to build Catch2, we also provide a couple of +integration points for our users. + +1) Catch2 exports a (namespaced) CMake target +2) Catch2's repository contains CMake scripts for automatic registration +of `TEST_CASE`s in CTest + +## CMake target + +Catch2's CMake build exports an interface target `Catch2::Catch2`. Linking +against it will add the proper include path and all necessary capabilities +to the resulting binary. + +This means that if Catch2 has been installed on the system, it should be +enough to do: +```cmake +find_package(Catch2 REQUIRED) +target_link_libraries(tests Catch2::Catch2) +``` + + +This target is also provided when Catch2 is used as a subdirectory. +Assuming that Catch2 has been cloned to `lib/Catch2`: +```cmake +add_subdirectory(lib/Catch2) +target_link_libraries(tests Catch2::Catch2) +``` + +## Automatic test registration + +Catch2's repository also contains two CMake scripts that help users +with automatically registering their `TEST_CASE`s with CTest. They +can be found in the `contrib` folder, and are + +1) `Catch.cmake` (and its dependency `CatchAddTests.cmake`) +2) `ParseAndAddCatchTests.cmake` + +If Catch2 has been installed in system, both of these can be used after +doing `find_package(Catch2 REQUIRED)`. Otherwise you need to add them +to your CMake module path. + +### `Catch.cmake` and `AddCatchTests.cmake` + +`Catch.cmake` provides function `catch_discover_tests` to get tests from +a target. This function works by running the resulting executable with +`--list-test-names-only` flag, and then parsing the output to find all +existing tests. + +#### Usage +```cmake +cmake_minimum_required(VERSION 3.5) + +project(baz LANGUAGES CXX VERSION 0.0.1) + +find_package(Catch2 REQUIRED) +add_executable(foo test.cpp) +target_link_libraries(foo Catch2::Catch2) + +include(CTest) +include(Catch) +catch_discover_tests(foo) +``` + + +#### Customization +`catch_discover_tests` can be given several extra argumets: +```cmake +catch_discover_tests(target + [TEST_SPEC arg1...] + [EXTRA_ARGS arg1...] + [WORKING_DIRECTORY dir] + [TEST_PREFIX prefix] + [TEST_SUFFIX suffix] + [PROPERTIES name1 value1...] + [TEST_LIST var] +) +``` + +* `TEST_SPEC arg1...` + +Specifies test cases, wildcarded test cases, tags and tag expressions to +pass to the Catch executable alongside the `--list-test-names-only` flag. + + +* `EXTRA_ARGS arg1...` + +Any extra arguments to pass on the command line to each test case. + + +* `WORKING_DIRECTORY dir` + +Specifies the directory in which to run the discovered test cases. If this +option is not provided, the current binary directory is used. + + +* `TEST_PREFIX prefix` + +Specifies a _prefix_ to be added to the name of each discovered test case. +This can be useful when the same test executable is being used in multiple +calls to `catch_discover_tests()`, with different `TEST_SPEC` or `EXTRA_ARGS`. + + +* `TEST_SUFFIX suffix` + +Same as `TEST_PREFIX`, except it specific the _suffix_ for the test names. +Both `TEST_PREFIX` and `TEST_SUFFIX` can be specified at the same time. + + +* `PROPERTIES name1 value1...` + +Specifies additional properties to be set on all tests discovered by this +invocation of `catch_discover_tests`. + + +* `TEST_LIST var` + +Make the list of tests available in the variable `var`, rather than the +default `_TESTS`. This can be useful when the same test +executable is being used in multiple calls to `catch_discover_tests()`. +Note that this variable is only available in CTest. + + +### `ParseAndAddCatchTests.cmake` + +`ParseAndAddCatchTests` works by parsing all implementation files +associated with the provided target, and registering them via CTest's +`add_test`. This approach has some limitations, such as the fact that +commented-out tests will be registered anyway. + + +#### Usage + +```cmake +cmake_minimum_required(VERSION 3.5) + +project(baz LANGUAGES CXX VERSION 0.0.1) + +find_package(Catch2 REQUIRED) +add_executable(foo test.cpp) +target_link_libraries(foo Catch2::Catch2) + +include(CTest) +include(ParseAndAddCatchTests) +ParseAndAddCatchTests(foo) +``` + + +#### Customization + +`ParseAndAddCatchTests` provides some customization points: +* `PARSE_CATCH_TESTS_VERBOSE` -- When `ON`, the script prints debug +messages. Defaults to `OFF`. +* `PARSE_CATCH_TESTS_NO_HIDDEN_TESTS` -- When `ON`, hidden tests (tests +tagged with any of `[!hide]`, `[.]` or `[.foo]`) will not be registered. +Defaults to `OFF`. +* `PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME` -- When `ON`, adds fixture +class name to the test name in CTest. Defaults to `ON`. +* `PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME` -- When `ON`, adds target +name to the test name in CTest. Defaults to `ON`. +* `PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS` -- When `ON`, adds test +file to `CMAKE_CONFIGURE_DEPENDS`. This means that the CMake configuration +step will be re-ran when the test files change, letting new tests be +automatically discovered. Defaults to `OFF`. + + +## CMake project options + +Catch2's CMake project also provides some options for other projects +that consume it. These are + +* `CATCH_BUILD_EXAMPLES` -- When `ON`, Catch2's usage examples will be +built. Defaults to `OFF`. +* `CATCH_INSTALL_DOCS` -- When `ON`, Catch2's documentation will be +included in the installation. Defaults to `ON`. +* `CATCH_INSTALL_HELPERS` -- When `ON`, Catch2's contrib folder will be +included in the installation. Defaults to `ON`. +* `BUILD_TESTING` -- When `ON` and the project is not used as a subproject, +Catch2's test binary will be built. Defaults to `ON`. + +--- + +[Home](Readme.md#top) diff --git a/docs/tutorial.md b/docs/tutorial.md index d55355c6..90dd2193 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -14,6 +14,9 @@ The simplest way to get Catch2 is to download the latest [single header version](https://raw.githubusercontent.com/CatchOrg/Catch2/master/single_include/catch.hpp). The single header is generated by merging a set of individual headers but it is still just normal source code in a header file. +Alternative ways of getting Catch2 include using your system package +manager, or installing it using its CMake package. + The full source for Catch2, including test projects, documentation, and other things, is hosted on GitHub. [http://catch-lib.net](http://catch-lib.net) will redirect you there. @@ -23,6 +26,9 @@ Catch2 is header only. All you need to do is drop the file somewhere reachable f The rest of this tutorial will assume that the Catch2 single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary. +_If you have installed Catch2 from system package manager, or CMake +package, you need to include the header as `#include `_ + ## Writing tests Let's start with a really simple example ([code](../examples/010-TestCase.cpp)). Say you have written a function to calculate factorials and now you want to test it (let's leave aside TDD for now).