Best practice is linking to lib or compiling source in unit tests

I want to ask what is your experience with getting a testable source in a unit testing application. Next structure

NiceLib
|-src
   |- MyNiceClass.h
   |- MyNiceClass.cpp
   |- CMakeLists.txt
|-test
   |- tester_MyNiceClass.cpp
   |- main.cpp
   |- CMakeLists.txt

      

The src library is compiled. The test creates an executable file Test. What is the best practice for implementing MyNiceClass.cpp in a test application. At the moment, I know of two options. The first option is to link a test executable to the library. The \ CMakeLists.txt test will look like this:

enable_testing()

include_directories(../src/)

add_executable(tester_NiceLib
   main.cpp
   tester_MyNiceClass.cpp
   )

add_test(NicLibTest tester_NiceLib)

target_link_libraries(tester_NiceLib NiceLib)

      

Second solution:

enable_testing()

include_directories(../src/)

add_executable(tester_NiceLib
   main.cpp
   tester_MyNiceClass.cpp

   ../src/MyNiceClass.h
   ../src/MyNiceClass.cpp
   )

add_test(NicLibTest tester_NiceLib)

      

What's your experience? Do you have any best practices, or perhaps other solutions?

+3


source to share


1 answer


What's your experience? Do you have any Best-Practices or maybe other solutions?

I use both (successfully), but which works best depends on the situation . If you only need one class, but your library contains many other things, this may be overkill. There is no overall "best solution".

Personally, I recommend that you just choose what works for your needs. No problem to switch between them at any other time.

However, it is best not to integrate the regular source files into your tests, as they need to be compiled multiple times (per test + production code). You can just include the actual Object files instead and only compile once. It also gives you more flexibility and better management of CMake dependencies.

So, here are my two options that I am using:

Option 1: Link Library

This is the same as your first option.

Assembly library:

add_library(dependencies-lib Src1.cpp Src2.cpp)

      

Link to tests:

# create test target ...
add_executable(exampletest SomeTests.cpp)
target_link_libraries(exampletest dependencies-lib)

      



Option 2: Add Object Library

This is almost the same as option 1, but you can be very selective. However, this prevents multiple compilation of the method on files with regular source code.

Build Object Library:

add_library(dependencies-lib OBJECT Src1.cpp Src2.cpp)
#                            ^^^^^^

      

Add objects in test:

# create test target ...
add_executable(exampletest SomeTests.cpp 
                        $<TARGET_OBJECTS:dependencies-lib> # <-- !!
                        )

      

As you can see, you are not linking it as a library, you are using compiled object files instead. Even if many other targets need them, they are only collected once. Btw. you can easily package them into a regular library / executable (e.g. for a productive binary / lib):

add_library(all-together-lib Source1.cpp
                Source2.cpp
                # ...

                $<TARGET_OBJECTS:dependencies-lib>
                $<TARGET_OBJECTS:dependencies-lib2>
                $<TARGET_OBJECTS:dependencies-lib3>
                $<TARGET_OBJECTS:dependencies-and-many-more>
                # ...

                # And some more source files ...
                Example1.cpp
                Example2.cpp
                # ...
                )

      

Documentation

+3


source







All Articles