How to create a template for creating a test executable using catch2 with qt and trompeloeil?

Viewed 310

I have a project (with main.cpp and some headers. Yes, it is a Catch2 test project as described in this blog). It compiles and runs.

My problem is: This project does nothing useful unless I add some more source files (my test cases). These source files use one header from the project and bring in some other dependencies as well (my library that I want to test).

The simple solution would be to copy this project, add the needed files and we are done.

Is there a better way? Currently with qmake I have the project defined in a catch.pri file. By including this in an project I have everything for the qt and catch2 setup, and only have to define the files with the testcases by modifying the SOURCES-Variable and the dependencies for the code to test.

Mapping this to CMake makes me ask questions:

First: when I include have a line like:

add_executable(tests main.cpp ${SOURCES})

Can I define SOURCES in a later line?

Second and more important: Is it a good idea to do it this way?

3 Answers

Can I define SOURCES in a later line?

Yes, but not the way you've done it. You can define your executable target tests with a few sources or no sources, but you can always append more sources later using the target_sources command.

add_executable(tests main.cpp)

...

# Later in the CMake file (or in another CMake file added via 'add_subdirectory').
target_sources(tests PRIVATE
    MyTestClass1.cpp
    MyTestClass2.cpp
    ...
)

You can similarly add compilation flags to this tests target later using target_compile_options, and add dependencies to link to tests using target_link_libraries.

Is there a better way?

No, this is how usually things are done. Any library / subproject is included using a .pri file. You can, of course, make the subproject a git-submodule.

Can I define SOURCES in a later line?

Short answer: No

Example:

Lets say we have a small project with a single file a.cpp and a CMakeLists.txt as follows:

cmake_minimum_required(VERSION 3.12)
project(testing)
add_executable(testing ${sources})
#defining ${sources} later
set(sources a.cpp)

if you try to build this, it will result in an error:

No SOURCES given to target: testing

I assume you want to separate the definition of sources variable to a separate file. In that case we can solve this as following. Assuming we have a dir structure as follows:

src/
|--lib/
|--tests/
|---- CMakeLists.txt
CMakeLists.txt
main.cpp

Our cmake file will be same as before with these additional changes before add_executable:

add_subdirectory(tests)

In the CMakeLists.txt file inside tests/ you can define the ${SOURCES} variable:

set(SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/test.cpp
    PARENT_SCOPE
)

Note that you need PARENT_SCOPE here to make this SOURCES variable visible to the parent directory, which in our case is src/

Now in our main CMakeLists.txt we can use this variable:

add_executable(tests ${SOURCES})

Second and more important: Is it a good idea to do it this way?

It depends. If you have a simple single directory project then it's not necessary. If you have multiple directories then of course, each directory should have its own CMake file which defines it's own variables. CMake files are code, they should be treated as code meaning they should be clean, modular and readable.

There is nothing wrong with defining the test_template as an static lib, which provides the main.cpp.

This way I define my tests as new executable, with test-files, library-dependencies and whatever, and only have to link to the static lib.

Related