find external test file for unit test by relative path c++ cmake guest

Pass the file name to gtest arguments:

add_executable(foo ...)
enable_testing()
add_test(FooTest foo "${CMAKE_CURRENT_LIST_DIR}/data/input.file")

get the parameter after gtest parse input:

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  assert(argc == 2); // gtest leaved unparsed arguments for you

and save it to some global *:

  file_name = argv[1];
  return RUN_ALL_TESTS();

* Usually it's not a very good idea to pollute the global namespace but I think it's fine for testing app

Related

  • How to pass parameters to the gtest

In your CMakefile, add your tests and set some an environment variable with the path to you data.

add_test(mytests ${PROJECT_BINARY_DIR}/unittests)
set_tests_properties(mytests PROPERTIES 
                     ENVIRONMENT
                     DATADIR=${CMAKE_CURRENT_SOURCE_DIR}/tests/testvectors)

You can later retrieve the DATADIR from the environment in any test.

You other option is to define a different working directory

set_tests_properties(mytests PROPERTIES
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests)

In my opinion, this is the less intrusive and simpler way.


I prefer to find my test data relative to my executable test. To do so, I usually define a helper method in some TestHelpers.h and then pass the relative path of the file I'm looking to resolve.

inline std::string resolvePath(const std::string &relPath)
{
    namespace fs = std::tr2::sys;
    // or namespace fs = boost::filesystem;
    auto baseDir = fs::current_path();
    while (baseDir.has_parent_path())
    {
        auto combinePath = baseDir / relPath;
        if (fs::exists(combinePath))
        {
            return combinePath.string();
        }
        baseDir = baseDir.parent_path();
    }
    throw std::runtime_error("File not found!");
}

To use it, I go:

std::string foofullPath = resolvePath("test/data/foo.txt");

and that gives me a full path of the test file as long as my executing directory runs from on a descendant of the project's root directory.