GTest and GMock integration with CMake

Testing the code… What is that ?

Well… We all know that guy that always tests it’s code in production. We don’t want to be “that guy”.

Before starting this out, I want to tell you that you can also find this information in video format on my YouTube channel (/c/cppdev), right here. This post will cover from the beginning until around the 10 min mark from the video. I will cover the actual tests implementation in later posts.

Now that we got this out of our way, let’s get to the fun stuff.

Maybe you have some project already setup with CMake as the main tool for your build system and now you don’t know what to do, or what is the next step. If you don’t already have the CMake project, you can check out this article or this article, which will help you setup your project.

I will tell you. The next step should be testing your code. In this post I will show you how you can setup the project so that you add GTest and GMock libraries to your project and use them later on to prepare test cases for your code.

What are GTest and GMock

To be short and precise, GTest is a framework for unit testing of your code and GMock is a framework imitating the rest of your system during unit tests.

The catch here is that GTest is a testing framework in itself and can be used standalone just to perform simple test cases that do not involve functionality of other systems/applications etc.

On the other hand, GMock is just a “utilitary library” that works very well with GTest, providing you support for “mocking” (imitating) the functionalities of other systems/applications so you can proceed with the testing of your own application.

“Google Mock is not a testing framework itself. Instead, it needs a testing framework for writing tests. Google Mock works seamlessly with Google Test. It comes with a copy of Google Test bundled. Starting with version 1.1.0, you can also use it with any C++ testing framework of your choice. “

– Google Mock, System Requirements

This should provide you a basic understand of what are both GTest and GMock.

If you need more information, you can also check out the actual documentation on the googletest github repository.

Prerequisites

Now that we got over that, we want to integrate GTest and GMock so we can test our code.

First of all, for this example, I will use repository structure as follows :

I’ve explained a little bit more about CMakeLists.txt in the previous blog post or in the YouTube video so you can check them out if you don’t know the concept.

Now, for the contents of the CMakeLists.txt files – before having GTest and GMock integrated – I will add them below. I will omit all the parts from the other CMakeLists.txt files that are irrelevant. I just want to show you the targets that we have before starting to add the libraries.

cpp-tutorial/src/CMakeLists.txt

# more code here ...

# the target that we want to test
add_executable(${PROJECT_ID})

The src CMakeLists.txt contains the target that we want to test – "${PROJECT_ID}"(which will translate to “cpp_tutorial“) executable.

Now for the test/CMakeLists.txt

# more code here ...

# simple test target
add_executable(${PROJECT_ID}-test)

The test/CMakeLists.txt also contains a target for the actual tests executable – "${PROJECT_ID}-test"(which will translate to “cpp_tutorial-test”). For the test cases, there is different target, which in turn, will use the code from the main target.

That should be all that you need to have before starting out to integrate the libraries with CMake.

Integrating the libraries with CMake

Having all that, now we can start with the GTest and GMock stuff.

First thing that we have to do, is to get the actual source code for the libraries (we are going to save them in "CPPTutorial/external" path. Please note that we are going to build them together with our project, in this case.

We can simply clone the repository with git from https://github.com/google/googletest.git using "git clone" command.

We will end up with this directory structure :

And we have everything we need, including the googletest repository which contains both GTest and GMock source code.

We have to add some changes to our CMakeLists.txt files in order to build, link and then generate some tests, all of that, using the newly cloned libraries.

Here are the changes done to the CMakeLists.txt files. The new added lines will be in green.

cpp-tutorial/src/CMakeLists.txt

# more code here ...


# add option to build also the test binary
option(BUILD_TESTS "Turn on build for tests of CPPTutorial" OFF)

# if we want to also build the test binary
# tell googletest to build GMOCK
# add_subdirectory for both external/googletest and test
# the add_subdirectory command will run CMakeLists.txt from given directory
if (BUILD_TESTS)
	set(BUILD_GMOCK ON)
	add_subdirectory(external/googletest)
	add_subdirectory(test)
endif()

# the target that we want to test

add_executable(${PROJECT_ID})

# we want to have a static library in order to link it to the test binary
# this will let us use the code used by "CPPTutorial" executable but without making it run by default with "main" function
# we will just have the code - but we won't run the binary itself 
# no main function
add_library(${PROJECT_ID}-static STATIC)

As you can see above, we also added the subdirectory for external/googletest – which will run the external/googletest/CMakeLists.txt code.

But you may ask, what CMakeLists.txt in the googletest directory ? We didn’t add any.

Well, yes, we didn’t add any CMakeLists.txt in the googletest directory, but when we cloned the repository, it also came with that file – which is set up by the googletest developers and we don’t want to mess with it.

Ok, let’s get on with the next CMakeLists.txt that we have to modify.

test/CMakeLists.txt

# more code here ...


# simple test target

add_executable(${PROJECT_ID}-test)

# we going to add a test (to be run later on)
# the test will have the name of the test executable
# the command will be "execution of the test executable"
add_test(NAME ${PROJECT_ID}-test COMMAND ${PROJECT_ID}-test)

# we want to link the ${PROJECT_ID}-static target in order for us to have the actual code that we want to test available in the test binary
# we also want to link the gtest and gmock libraries here
# this is the scope of the tutorial, right !?
target_link_libraries(${PROJECT_ID}-test
    PUBLIC
        ${PROJECT_ID}-static
        gtest
        gmock
)

And that’s it.

We have integrated GTest and GMock libraries in our test binary and we can now use everything provided by these two libraries.

We can use stuff from the “testing” namespace like “Test“, “EXPECT_CALL“, “EXPECT_EQ“, “MOCK_METHOD” and many others, but these will probably be covered in future posts since it is not the scope of this one.

Source Code

You can find the full source code for the project on my github. There are steps on how to build and test the code provided in README file.

In the end…

It doesn’t even matter. All that matters is that now you can test your code before production and you won’t be “that guy”. As for actual implementation of the test cases… that is a story for another time :).

I hope you learned something new today and maybe this helped you in your programming career.

If you find my posts useful, don’t forget to like and also take a look at my YouTube channel – there are more things there that you might like related to programming and more.

1 thought on “GTest and GMock integration with CMake”

  1. Pingback: Test Cases using GTest (Unit Testing) – The CPPDEV

Leave a Reply

%d bloggers like this: