简体   繁体   中英

How can I use Catch2 to test my CMake static library project?

I'm writing a static library which contains some shared code between several projects. In order to verify that the code in this library functions properly I'd like to use Catch2 to do some unit testing on it.

Unfortunately, when attempting to run the tests I run into the problem that the compilation's output file is a shared library (.a), rather than an executable.

I'm sure I can create a separate project which uses the functions from my static library, and subsequently run tests that way, but ideally I'd like to keep the tests and build configurations as close as possible to one another.

So my question is: what's the best way to set up my project such that I can use Catch2 for unit testing my static library code?

Here's my project's CMakeLists.txt file for reference:

project(sharedLib CXX)

find_package(OpenMP)

if (CMAKE_COMPILER_IS_GNUCC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp -lpthread -Wall -Wextra -Wpedantic -std=c++17")
endif()

if (MSVC)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /fopenmp /W4 /std:c++latest")
endif()

include_directories (
        src/
        lib/Catch2/single_include/
)

file (GLOB_RECURSE LIBRARY_SOURCES src/*.cpp
                                   src/*.c
                                   tests/*.cpp)

add_library(${PROJECT_NAME} STATIC ${LIBRARY_SOURCES})

target_include_directories(${PROJECT_NAME} PUBLIC src/)

As already stated in the catch2 tag wiki info (emphasis mine):

it is released as a single include file and allows the use of natural C++ expressions inside assertions

Thus there's no need to add any library for it. Including the header in your unit testing source code is enough.

Same stated at the readme page at the hosted GitHub project:

What's the Catch?

Catch2 stands for C++ Automated Test Cases in a Header and is a multi-paradigm test framework for C++. which also supports Objective-C (and maybe C). It is primarily distributed as a single header file , although certain extensions may require additional headers.

Just make sure you have a unit test runner executable, providing a main() function definition calling all of your unit test functions. As from their tutorial it can be easily done like so:

 #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file

Unfortunately, when attempting to run the tests I run into the problem that the compilation's output file is a shared library (.a), rather than an executable.

Well, you have declared your CMake project type like that:

 project(sharedLib CXX)

For more information about how to setup CMake unit test projects properly see this Q&A

please.

A common pattern for testing static libraries is to have a separate executable which contains all the tests, and then consumes your library. for example

file (GLOB_RECURSE TEST_SOURCES tests/*.cpp)
add_executable(my_lib_tests test_main.cpp ${TEST_SOURCES})
target_link_libraries(my_lib_tests PRIVATE sharedLib)
target_include_directories(my_lib_tests PRIVATE ../path/to/secret/impl/details)

Here I also have added some include some directories to implementation details of your shared lib which you may need to test, but don't want to expose to clients via a public header.

test_main.cpp need only be:

#define CONFIG_CATCH_MAIN
#include <catch2/catch.hpp>

Then you don't have to include things in your library's build that are unrelated to the library itself, speeding up compilation time for clients, while you can work from the perspective of the test fixture

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM