Tests are one of the most important parts of any CD/CI system. It helps you to ensure that a section of an application or your new codes(the unit) meet their design and behave as intended. By writing tests first for the smallest testable units, then the compound behaviors between those, one can build up comprehensive tests for complex applications. You may ask what makes a good test? Tests should be independent, repeatable, portable, reusable, well organized, provide as much information about the problem as possible, and finally, tests should be fast. GoogleTest, Google’s C++ test framework, has it all!
Googletest is a testing framework developed by the Testing Technology team. Whether you work on Linux, Windows, or a Mac, if you write C++ code, Googletest can help you. And it supports any kind of tests, not just unit tests. it supports GCC 5.0+, Clang 5.0+, and MSVC 2015+ and also can be used in CMake and Bazel build system.
Assert or Expect… that is the question!
When using Googletest, you start by writing assertions, which are statements that check whether a condition is true. An assertion’s result can be a success, nonfatal failure (EXPECT_
), or fatal failure (ASSERT_EQ
). If a fatal failure occurs, it aborts the current function; otherwise, the program continues normally.
Tests use assertions to verify the tested code’s behavior. If a test crashes or has a failed assertion, then it fails; otherwise, it succeeds. You can find a very well written primer about it here: https://google.github.io/googletest/primer.html
gMock! that is the answer!
When you write a prototype or test, often it’s not feasible or wise to rely on real objects entirely you have to mock it. Let say the class or the method you intended to test connects to an HTTPS server or communicates with some sophisticated hardware then gMock is the answer! When I write a Java code I have tons of tools to test and mock easily but using mocks manually in C++ is really hard! Google says: “gMock turns this task into a fun game! (Well, almost.)” You can find recipes for using gMock here. https://google.github.io/googletest/gmock_cook_book.html
Creating a basic test… RUN_ALL_TESTS(); please!
To setup gTest in Ubuntu, you need to run this set of commands:
sudo apt-get install libgtest-dev cd /usr/src/gtest sudo cmake CMakeLists.txt sudo make sudo cp lib/*.a /usr/lib
and let say you want to test this part of the code:(save it as main.cpp
)
// main.cpp #include <math.h> double squareRoot(const double a) { if(a < 0) { return -1.0; }else{ return sqrt(a); } }
Now you need to creat your first basic test and run it.(save it as tests.cpp
)
#include "gtest/gtest.h" #include "main.cpp" TEST(SquareRootTest, PositiveNos) { EXPECT_EQ(3, squareRoot(9)); EXPECT_EQ(25.4, squareRoot(645.16)); EXPECT_EQ(50.3321, squareRoot(2533.310224)); EXPECT_DOUBLE_EQ(50.3321, squareRoot(2533.310224)); EXPECT_NEAR(50.3321, squareRoot(2533.310224),0.0001); } TEST(SquareRootTest, ZeroAndNegativeNos) { ASSERT_EQ(0.0, squareRoot(0.0)); ASSERT_EQ(-1, squareRoot(-22.0)); } int main(int argc, char **argv) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
Keep it in your mind gTest needs pthread! so we need to link them in the CMakeLists.txt
file:
cmake_minimum_required(VERSION 2.6) # Locate GTest find_package(GTest REQUIRED) include_directories(${GTEST_INCLUDE_DIRS}) # Link runTests and the GTest and pthread library add_executable(runTests tests.cpp) target_link_libraries(runTests ${GTEST_LIBRARIES} pthread)
Now you just need to compile and test it:
cmake CMakeLists.txt make ./runTests
And here it is your test output:
[==========] Running 2 tests from 1 test suite. [----------] Global test environment set-up. [----------] 2 tests from SquareRootTest [ RUN ] SquareRootTest.PositiveNos /tests.cpp:7: Failure Expected equality of these values: 50.3321 squareRoot(2533.310224) Which is: 50.332 /tests.cpp:8: Failure Expected equality of these values: 50.3321 Which is: 50.332099999999997 squareRoot(2533.310224) Which is: 50.332000000000001 [ FAILED ] SquareRootTest.PositiveNos (0 ms) [ RUN ] SquareRootTest.ZeroAndNegativeNos [ OK ] SquareRootTest.ZeroAndNegativeNos (0 ms) [----------] 2 tests from SquareRootTest (0 ms total) [----------] Global test environment tear-down [==========] 2 tests from 1 test suite ran. (0 ms total) [ PASSED ] 1 test. [ FAILED ] 1 test, listed below: [ FAILED ] SquareRootTest.PositiveNos 1 FAILED TEST
It fails! yes, It does! 🙂 we will talk about it and discuss what is that failure means! we will practice object mocking and more. Stay tuned!
References:
http://code.google.com/p/googletest/wiki/Documentation
http://www.ibm.com/developerworks/aix/library/au-googletestingframework.html
https://www.eriksmistad.no/getting-started-with-google-test-on-ubuntu/