Unit tests...
Essentially none, but writing unit tests ...
For writing, compiling and running unit tests, a unit testing framework is required.
There are many concurring unit testing frameworks for C++.
At the time of this writing, Boost Test and GoogleTest stand out in terms of quality and features.
// Return the sum of all values from 1 to n.
unsigned long long add_to(unsigned n) {
unsigned long long sum = 0;
for (unsigned i = 1; i <=n; ++i) {
sum += i;
}
return sum;
}
Download before_refactoring.cpp
After experiencing performance problems, we want to use a faster algorithm
// Return the sum of all values from 1 to n.
unsigned long long add_to(unsigned n) {
return (unsigned long long) (n / 2.0) * (n + 1);
}
Download after_refactoring.cpp
How can we apply the change without risking to destroy our application?
Using pencil and paper / brainstorming: define relevant test cases
25 is a possible common case.
Add 26 as an even input.
The edge cases should
include 0 and 4294967295.
Expected results for these are 325, 351, 0 and 9223372034707292160.
Let's also add 500000000 (expected result 125000000250000000) as 4294967295 does not terminate with the current implementation.
#include "gtest/gtest.h"
unsigned long long add_to(unsigned n); // usually in header file
TEST(sum_to, fast_test) {
EXPECT_EQ(add_to(0), 0);
EXPECT_EQ(add_to(25), 325);
EXPECT_EQ(add_to(26), 351);
EXPECT_EQ(add_to(500000000), 125000000250000000);
}
// does not terminate for the old code version due to an overflow of the
// loop counter (the loop would terminate only at UINT_MAX + 1)
TEST(sum_to, slow_test) {
EXPECT_EQ(add_to(4294967295), 9223372034707292160);
}
Download test_sum_to.cpp
clang++ before_refactoring.cpp test_sum_to.cpp -lgtest_main -lgtest -o run_tests
./run_tests # does not terminate; interrupt via [Ctrl]+[C]
What to do now?
./run_tests --help
./run_tests --gtest_list_tests # list all available tests
./run_tests --gtest_filter=sum_to.fast_test
For the sake of the presentation, instead of applying the change, we use another source file.
clang++ after_refactoring.cpp test_sum_to.cpp -lgtest_main -lgtest -o run_tests
./run_tests
Now the tests are fast, but they are failing. Fix the code, then compile and run the tests again.
sudo apt install googletest
sudo mkdir /usr/src/googletest/build
sudo chown $USER /usr/src/googletest/build
cd /usr/src/googletest/build
cmake ..
make -j4
sudo make install
sudo ldconfig
For other operating systems, follow the instructions in project's README.
Comprehensive documentation can be found in GoogleTest User’s Guide.
Whenever you are tempted to type something into a print
statement or a debugger expression, write it as a test instead.