본문 바로가기
Embedded

[Embedded] Unittest using GoogleTest on CMake

by llHoYall 2021. 10. 13.

In this posting, we will learn how to run a unittest for C.

We will use GoogleTest and CMake for this.

Prerequisite

CMake

Please refer to this post.

2021.10.13 - [Embedded] - [C] Build using CMake

GoogleTest

Clone the googletest into your project.

$ git clone https://github.com/google/googletest/

Prepare Project

This is the project tree.

+-- src
    +-- main.c
    +-- calc.h
    +-- calc.c
+-- googletest
+-- CMakeLists.txt

And, this is the code for unittest.

// src/main.c

#include "calc.h"

int main(int argc, char* argv[]) {
    return 0;
}

// src/calc.h

#ifndef __CALC_H__
#define __CALC_H__

extern int add(int x, int y);
extern int mult(int x, int y);

#endif

// src/calc.c

#include "calc.h"

int add(int x, int y) {
  return x + y;
}

int mult(int x, int y) {
  return x * y;
}

We will test the add and mult function.

Lastly, it's the CMake file.

# CMakeLists.txt

cmake_minimum_required(VERSION 3.0.0)

project(gtest_example VERSION 1.0.0)

add_subdirectory(googletest)

add_executable(gtest_example src/main.c src/calc.c)

Now, let's check the build.

$ mkdir build && cd build
$ cmake ..
$ cmake --build .

googletest already has the CMake configuration, so I added it via add_subdirectory().

Add Test

Add these codes into our project.

// test/main.cpp

#include "gtest/gtest.h"

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

// test/test_calc.cpp

#include "gtest/gtest.h"
extern "C" {
#include "calc.h"
}

TEST(CalcTest, testAdd) {
  EXPECT_EQ(add(1, 2),  3);
  EXPECT_EQ(add(3, -5), -2);
}

TEST(CalcTest, testMult) {
  EXPECT_EQ(mult(1, 2),  2);
  EXPECT_EQ(mult(3, -5), -15);
}

Let's modify CMake configuration in order to test.

cmake_minimum_required(VERSION 3.0.0)

# Main Project
project(gtest_example VERSION 1.0.0)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)

include_directories(src)

add_subdirectory(googletest)

add_executable(gtest_example src/main.c src/calc.c)

# Test Project
project(gtest_run)

enable_testing()

add_executable(gtest_run test/main.cpp test/test_calc.cpp src/calc.c)

target_link_libraries(gtest_run gtest)

add_test(NAME gtest_run COMMAND gtest_run)

I added a new project for testing.

I tried to look as easy as possible.

$ cmake ..
$ cmake --build .
$ make test

Great! It looks good!!

You can also run the test directly.

$ ./bin/gtest_run

Please check the failure case as well.

Refactoring

We can more clean up the CMake configuration.

It can be achieved in various ways.

I will make a static library with calc and separate the CMake configuration for testing.

# CMakeLists.txt

cmake_minimum_required(VERSION 3.0.0)

enable_testing()

# Main Project
project(gtest_example VERSION 1.0.0)

set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)

include_directories(src)

add_subdirectory(googletest)
add_subdirectory(test)

add_library(calc src/calc.c)

add_executable(gtest_example src/main.c)

target_link_libraries(gtest_example calc)

------------------------------
# test/CMakeLists.txt

set(TEST_BINARY ${CMAKE_PROJECT_NAME}_test)

add_executable(${TEST_BINARY} main.cpp test_calc.cpp)

target_link_libraries(${TEST_BINARY} gtest calc)

add_test(NAME ${TEST_BINARY} COMMAND ${TEST_BINARY})

It functions exactly the same thing as before.

Conclusion

Now we can run C unittest with GoogleTest on CMake.

댓글