1
votes

I am trying to find the best way to link my project source code with my boost unit tests. I have a fairly basic project setup right now using CMake, however all examples of boost UTF that I have come across have shown very basic tests which do not touch source code in a project that is along side the tests.

As a minimal example I have the following:

CMakeLists.txt

cmake_minimum_required(version 2.8) 
project(test-project) 
find_package(Boost 1.55 REQUIRED COMPONENTS unit_test_framework )
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})

add_subdirectory(src) 
enable_testing()
add_subdirectory(test) 

src/CMakeLists.txt

add_executable(example main.cpp foo.cpp)  

src/foo.h

#include <string>
std::string hello(std::string name);

src/foo.cpp

#include "foo.h"
std::string hello(std::string name) { return "Hello " + name; }

src/main.cpp - Uses foo in a simple way

test/CMakeLists.txt

include_directories (../src) 
set(TEST_REQUIRED_SOURCES ../src/foo.cpp)

add_executable (test test.cpp ${TEST_REQUIRED_SOURCES}) 
target_link_libraries(test ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})

add_test(SimpleTest test)

test/test.cpp

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE SimpleTest
#include <boost/test/unit_test.hpp>

#include "foo.h"

BOOST_AUTO_TEST_CASE(ShouldPass) {
    BOOST_CHECK_EQUAL(hello("fred"), "Hello fred")
}

While this works, I'd like to avoid the following:

  1. Defining TEST_REQUIRED_SOURCES with a list of all of my files required to compile.
  2. Avoiding the duplicate compilation of code.

Does my structure look correct for this sort of project? Would it make sense to compile my code under src into a library instead? Most of my experience with testing is from C# where this is much simpler.

1

1 Answers

1
votes

You can have a look at how I did it there: https://github.com/NewbiZ/mengine/blob/master/CMakeLists.txt

Basically, I build an object file with my library, and reuse it in the main executable AND the tests. That way you only build once.

The interesting piece of CMake is:

# Just build the object files, so that we could reuse them
# apart from the main executable (e.g. in test)
ADD_LIBRARY(mengine_objects OBJECT ${MENGINE_SOURCES})

Then build the main executable:

ADD_EXECUTABLE(mengine $<TARGET_OBJECTS:mengine_objects>
                       src/main.cpp)

And the tests:

ADD_EXECUTABLE(test_tga $<TARGET_OBJECTS:mengine_objects>
                        test_tga.cpp)

Hope that helps!