Test Driven Development with Google Test
Requirements:
g++
andCMake
installed
Steps:
- Create the source file.
- Create the
CMakeLists.txt
file. A basic starting point for creatingCMakeLists.txt
files - Create a
build
folder. - Inside the created build folder run
cmake ..
for generating the build files; - Again inside the created build folder run
make
for building and linking; - Execute the program.
Afterwards you should have the following folder structure:
.
├── build
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── hello_world
│ └── Makefile
├── CMakeLists.txt
└── src
└── hello_world.cpp
You have several ways of doing this which are explained in the GTest Documentation.
I went for the Standalone CMake Project:
- Followed the steps on the documentation.
- Created a folder for the tests.
- Added a
CMakeLists.txt
for the tests folder - Updated the main
CMakeLists.txt
to include the tests:
add_subdirectory(googletest)
add_subdirectory(tests)
- Filled the
CMakeLists.txt
of the tests. - Compiled again (with
make
inside the build folder). - The tests will be inside
build/tests
.
Every time you want to had a new test you just need to add the following lines:
add_executable(ut_hello_world ut_hello_world.cpp)
target_link_libraries(ut_hello_world gtest_main)
add_test(NAME ut_hello_world_test COMMAND ut_hello_world)
Now your folding structure should look like this:
.
├── build
│ ├── bin
│ ├── CMakeCache.txt
│ ├── CMakeFiles
│ ├── cmake_install.cmake
│ ├── CTestTestfile.cmake
│ ├── googletest
│ ├── hello_world
│ ├── lib
│ ├── Makefile
│ ├── Testing
│ └── tests
├── CMakeLists.txt
├── googletest
│ ├── ...
├── src
│ └── hello_world.cpp
└── tests
├── CMakeLists.txt
└── ut_hello_world.cpp
Imagine we need to create a function that divides 2 values:
- Create simple test case
TEST(Functions, Division)
{
EXPECT_EQ(division(4, 2), 2);
}
- See the compilation fail
error: ‘division’ was not declared in this scope
EXPECT_EQ(division(4, 2), 2);
- Make it compile the fastest way possible
int division(int a, int b)
{
return 0;
}
- Run the test and see it fail (RED Phase)
Expected equality of these values:
division(4, 2)
Which is: 0
2
[ FAILED ] Functions.Division (0 ms)
- Create logic only to make the existent test cases pass (REFACTOR Phase)
int division(int a, int b)
{
return a / b;
}
- Run test cases and see them pass (GREEN Phase)
[----------] 1 test from Functions
[ RUN ] Functions.Division
[ OK ] Functions.Division (0 ms)
[----------] 1 test from Functions (0 ms total)
- Go back to add more test cases to make sure that your functions accomplishes everything that is expected
EXPECT_EQ(division(4, 0), 0);
- Run test cases (RED Phase)
- Refactor production code to make the new existent test cases pass
int division(int a, int b)
{
if (0 == b)
{
std::cout << "Math error: Attempted to divide by Zero" << std::endl;
return 0;
}
return a / b;
}
- Run tests and see them pass (GREEN Phase)