I am currently trying to get a project setup with code coverage and testing that is in C. My current stack is CLion for an IDE, Clang for the compiler, gcov and lcov for coverage, Unity for a testing framework, and CMock for mocking/stubbing during tests.
I currently have the following package structure:
app/root
| build
| *.*
|- cmake
|- modules
|- CodeCoverage.cmake
|- coverage
|- coverage.info
|- external
|- Unity
|- CMock
|- CMakeLists.txt
|- src
|- *.c
|- *.h
|- CMakeLists.txt
|- tests
|- *.c
|- *.h
|- CMakeLists.txt
|- CMakeLists.txt
My higher level CMakeLists.txt looks like:
cmake_minimum_required(VERSION 3.6)
project(my_c_app)
set(CMAKE_C_COMPILER "/usr/bin/clang")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake/modules)
set(CMAKE_VERBOSE_MAKEFILE ON)
add_subdirectory(external)
add_subdirectory(src)
add_subdirectory(tests)
My app level CMakeLists.txt looks like:
SET(CMAKE_CXX_FLAGS "-O0")
SET(CMAKE_C_FLAGS "-DLINUX -O0 -Wall -std=c99")
set(SOURCE_FILES
util.c
util.h)
add_executable(my_c_app ${SOURCE_FILES})
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(my_c_app Threads::Threads)
target_include_directories(my_c_app PUBLIC ${PROJECT_SOURCE_DIR}/include)
My test level CMakeLists.txt looks like:
enable_testing()
include(CodeCoverage)
include(CTest)
SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
SET(CMAKE_C_FLAGS "-DLINUX -O0 -Wall -std=c99 -g -fprofile-arcs -ftest-coverage")
SETUP_TARGET_FOR_COVERAGE(coverage tests ${PROJECT_SOURCE_DIR}/coverage/coverage "'/usr/*';'tests/*';'external/*'")
add_executable(tests util_test.c)
target_link_libraries(tests Unity CMock)
add_test(tests util_test.c)
Currently my issue is I'm not doing something correctly. I am getting an undefined reference while trying to test a function in util.c:
CMakeFiles/tests.dir/util_test.c.o: In function `test_my_method':
/home/patches/my_c_app/tests/util_test.c:6: undefined reference to `my_method'
My util_test.c currently is:
#include <unity.h>
#include "../src/util.h"
void test_my_method(void) {
uchar result = my_method();
// assertion and other logic would go here
}
int main(void) {
UNITY_BEGIN();
RUN_TEST(test_my_method);
return UNITY_END();
}
I'm a noob at test driven c development and CMake, so what is the proper way I am supposed to setup my tests so that they are dependent on the c files in src?
If I just do a TEST_ASSERT_EQUAL(1,1) instead of placing a call into the util.c function I do see:
1 Tests 0 Failures 0 Ignores
OK
Process finished with exit code 0
so I feel like I'm 100% stuck on a linker issue of some sort.