SRG
SRG

Reputation: 269

CMake + GoogleTest not running tests, no output

I would like some help setting up google test and cmake. I am using Visual Studio 2017 as my ide/compiler.

My main problem is that I am not sure whether my tests are getting run or even working! I run the RUN_TESTS project and everything seems to run ok but I don't get any print out that google test main ran. e.g "Running main() from gtest_main.cc" etc.

This is what I would like...

  1. keep my project code separate from test code
  2. the option of having my code (the classes to be tested) as part of a project
  3. or as a separate library that a project links to.

I would like my tests to be able to handle both cases 2) & 3).

I also am including my code in my test executable like below which I don't think is the right way to do it.

add_executable (unit_tests example.h example.cpp test/example_add.cpp test/example_subtract.cpp)

And also I am using #include "../example.h" in my test files to include my code to be tested. I don't think that is right. CMake should have already added the include path to the project settings?

I have the following folder structure for my cmake project. example.h/.cpp is some code that I want to be tested. It is currently set up within a project like I describe in case 2) above.

\Project2

---\src
------CMakeLists.txt
------CMakeLists.txt.in
------example.cpp
------example.h
------main.cpp
------\test
---------example_add.cpp
---------example_subtract.cpp

CMakeLists.txt

cmake_minimum_required (VERSION 3.9)
project (Project2)

include (CTest)

# The version number.
set (Project2_VERSION_MAJOR 1)
set (Project2_VERSION_MINOR 0)

# add the binary tree to the search path for include files
# so that we will find Project1Config.h
include_directories ("${PROJECT_BINARY_DIR}")

# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
  RESULT_VARIABLE result
  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
if(result)
  message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
  RESULT_VARIABLE result
  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
if(result)
  message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()

# Prevent overriding the parent project's compiler/linker
# settings on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)

# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
                 ${CMAKE_BINARY_DIR}/googletest-build
                 EXCLUDE_FROM_ALL)

# The gtest/gtest_main targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later. Otherwise, we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11)
  include_directories("${gtest_SOURCE_DIR}/include")
endif()

# add the executable
add_executable (Project2 main.cpp example.h example.cpp)
target_link_libraries(Project2 gtest_main)
target_link_libraries (Project2 ${EXTRA_LIBS})

add_executable (unit_tests example.h example.cpp test/example_add.cpp test/example_subtract.cpp)
target_link_libraries (unit_tests gtest_main)
#
#
#   INSTALL
#
#

# add the install targets
install (TARGETS Project2 DESTINATION bin)

#
#
#   TESTS
#
#

add_test (NAME example_test COMMAND Project2)
add_test (NAME unit COMMAND ${CMAKE_BINARY_DIR}/unit_tests)

CMakeLists.txt.in

cmake_minimum_required(VERSION 3.9)

project(googletest-download NONE)

include(ExternalProject)
ExternalProject_Add(googletest
  GIT_REPOSITORY    https://github.com/google/googletest.git
  GIT_TAG           master
  SOURCE_DIR        "${CMAKE_BINARY_DIR}/googletest-src"
  BINARY_DIR        "${CMAKE_BINARY_DIR}/googletest-build"
  CONFIGURE_COMMAND ""
  BUILD_COMMAND     ""
  INSTALL_COMMAND   ""
  TEST_COMMAND      ""
)

example.h

#pragma once

double add_numbers(const double f1, const double f2);

double subtract_numbers(const double f1, const double f2);

double multiply_numbers(const double f1, const double f2);

example.cpp

#include "example.h"

double add_numbers(const double f1, const double f2)
{
    return f1 + f2;
}

double subtract_numbers(const double f1, const double f2)
{
    return f1 - f2;
}

double multiply_numbers(const double f1, const double f2)
{
    return f1 * f2;
}

main.cpp

#include <iostream>

int main()
{
    std::cout << "hello, world!" << std::endl;

    return 0;
} 

example_add.cpp

#include "gtest/gtest.h"
#include "../example.h"

TEST(example, add)
{
    double res;
    res = add_numbers(1.0, 2.0);
    ASSERT_NEAR(res, 3.0, 1.0e-11);
}

example_subtract.cpp

#include "gtest/gtest.h"
#include "../example.h"

TEST(example, subtract)
{
    double res;
    res = subtract_numbers(1.0, 2.0);
    ASSERT_NEAR(res, -1.0, 1.0e-11);
}

Upvotes: 1

Views: 6446

Answers (3)

fjhaha
fjhaha

Reputation: 1

The point is you need the initialization/execution code to run somewhere, somehow by the executable that you run. If you don't create a main function, it's imported automatically from the gtest_main library (gtest_main.cc) by the linker[1]. You can just as well make your own combined version of the above, if you want:

int main(int argc, char** argv)
{
    std::cout << "hello, world!" << std::endl;

    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
} 

[1] so long as the linker knows to import it (by the fact that you reference it somewhere at link-time for example). With VS, the linker command can include for example /subsystem:console plus links shell32.lib, whose libraries reference main internally. Linking then forces a search for main, so things "just work". If for some reason your project doesn't use those options, there's also linker options that force importing even unreferenced functions. Or you can also forcibly reference main in your source file somewhere with tricks or by example just:

extern "C" int main(int, char**);
void _force_reference() { main(0, nullptr); }

Upvotes: 0

SRG
SRG

Reputation: 269

The problem was i had two main() functions. I removed the main in my unit tests project and the main in gtestmain.cc was correctly called.

Upvotes: 4

Wael Boutglay
Wael Boutglay

Reputation: 1373

In the main function of your test executable, you must have something similar to this

::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();

What you should do is to add another file to your test directory that should contain a code like this one:

// test executable
#include "gtest/gtest.h"
#include "example_add.cpp"
#include "example_substract"

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Upvotes: 0

Related Questions