I have a bunch of unit tests I want to migrate from Visual Studio's test framework to something more accessible. I started moving some to ctest, where (as I understand) each test needs to compile to a separate executable.
My cmakelists.txt looks like:
cmake_minimum_required(VERSION 3.10)
project(UnitTests)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MACOSX_RPATH 1)
include(CTest)
enable_testing()
add_executable(Test1 Test1.cpp)
add_executable(Test2 Test2.cpp)
add_test(First Test1)
add_test(Second Test2)
The problem is that Test1 and Test2 compile to files of 2.7 and 2.6 MB, respectively. This is because each has to have #include "BigClass.h"
, where BigClass
is the big, sprawling project I actually want to test.
I have maybe a few dozen tests I want to migrate, so to compile and run all these tests would likely run into hundreds of megabytes of executables, where most of the space is simply repeating all the code from BigClass
!
I tried to include this class as a library with:
add_library(BigClass SHARED ../path/to/BigClass.cpp)
and then at the end of the file:
target_link_libraries(Test1 PUBLIC BigClass)
but this did not affect the space.
I think what I want is a way to dynamically link to BigClass
(which would be compiled already anyway), so all the tests can share the code. But I'm not sure how to do this and I'm not quite sure how to search for it (searching for dynamically linked #include
reveals that this is not really possible, for example).
Can anyway help me find either:
- a cross-platform C testing framework that avoids all these problems?
- a way to compile unit tests in ctest to share a lot of the same code?
- directions on how to link C classes dynamically?
CodePudding user response:
- a cross-platform C testing framework that avoids all these problems?
Ignoring the fact that code recommendations are off-topic…
We are using
The build artefacts of Visual Studio 2019:
Running Test1.exe
:
Test1:
======
BigClass big;
big.print();
BigClass::print(): *this: BigClass { id: 0 }
big.printLn();
BigClass::print(): *this: BigClass { id: 0 }
BigClass big1(1);
big1.print();
BigClass::print(): *this: BigClass { id: 1 }
big1.printLn();
BigClass::print(): *this: BigClass { id: 1 }
Done.
Running Test2.exe
:
Test2:
======
BigClass big;
print(big);
print(): BigClass::print(): *this: BigClass { id: 0 }
printLn(big);
BigClass::print(): *this: BigClass { id: 0 }
BigClass big2(2);
print(big2);
print(): BigClass::print(): *this: BigClass { id: 2 }
printLn(big2);
BigClass::print(): *this: BigClass { id: 2 }
Done.
Finally (to address the portability), I built the same CMake project in Linux:
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C /dll$ mkdir build-Linux
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C /dll$ cd build-Linux
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C /dll/build-Linux$ ccmake ..
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C /dll/build-Linux$ cmake --build .
Scanning dependencies of target BigClass
[ 16%] Building CXX object CMakeFiles/BigClass.dir/BigClass.cc.o
[ 33%] Linking CXX shared library libBigClass.so
[ 33%] Built target BigClass
Scanning dependencies of target Test2
[ 50%] Building CXX object CMakeFiles/Test2.dir/Test2.cc.o
[ 66%] Linking CXX executable Test2
[ 66%] Built target Test2
Scanning dependencies of target Test1
[ 83%] Building CXX object CMakeFiles/Test1.dir/Test1.cc.o
[100%] Linking CXX executable Test1
[100%] Built target Test1
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C /dll/build-Linux$ ls
CMakeCache.txt CMakeFiles cmake_install.cmake libBigClass.so Makefile Test1 Test2
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C /dll/build-Linux$ ./Test1
Test1:
======
BigClass big;
big.print();
BigClass::print(): *this: BigClass { id: 0 }
big.printLn();
BigClass::print(): *this: BigClass { id: 0 }
BigClass big1(1);
big1.print();
BigClass::print(): *this: BigClass { id: 1 }
big1.printLn();
BigClass::print(): *this: BigClass { id: 1 }
Done.
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C /dll/build-Linux$ ./Test2
Test2:
======
BigClass big;
print(big);
print(): BigClass::print(): *this: BigClass { id: 0 }
printLn(big);
BigClass::print(): *this: BigClass { id: 0 }
BigClass big2(2);
print(big2);
print(): BigClass::print(): *this: BigClass { id: 2 }
printLn(big2);
BigClass::print(): *this: BigClass { id: 2 }
Done.
Scheff'sCat@debian:/mnt/hgfs/hostD/Entwicklung/tests/C /dll/build-Linux$