Testing And Benchmarking in C++
Here’s the translation of the Go testing and benchmarking example to C++:
#include <iostream>
#include <vector>
#include <chrono>
#include <cassert>
// We'll be testing this simple implementation of an
// integer minimum. Typically, the code we're testing
// would be in a source file named something like
// `intutils.cpp`, and the test file for it would then
// be named `intutils_test.cpp`.
int IntMin(int a, int b) {
if (a < b) {
return a;
}
return b;
}
// A test is created by writing a function.
void TestIntMinBasic() {
int ans = IntMin(2, -2);
if (ans != -2) {
throw std::runtime_error("IntMin(2, -2) = " + std::to_string(ans) + "; want -2");
}
}
// Writing tests can be repetitive, so it's idiomatic to
// use a table-driven style, where test inputs and
// expected outputs are listed in a table and a single loop
// walks over them and performs the test logic.
struct TestCase {
int a;
int b;
int want;
};
void TestIntMinTableDriven() {
std::vector<TestCase> tests = {
{0, 1, 0},
{1, 0, 0},
{2, -2, -2},
{0, -1, -1},
{-1, 0, -1},
};
for (const auto& tt : tests) {
int ans = IntMin(tt.a, tt.b);
if (ans != tt.want) {
throw std::runtime_error("IntMin(" + std::to_string(tt.a) + ", " +
std::to_string(tt.b) + ") = " +
std::to_string(ans) + "; want " +
std::to_string(tt.want));
}
}
}
// Benchmark tests typically go in separate files and are
// named beginning with `Benchmark`. In C++, we can use
// the chrono library to measure execution time.
void BenchmarkIntMin() {
const int N = 1000000;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < N; i++) {
IntMin(1, 2);
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start);
std::cout << "BenchmarkIntMin: " << duration.count() / N << " ns/op" << std::endl;
}
int main() {
try {
std::cout << "Running TestIntMinBasic..." << std::endl;
TestIntMinBasic();
std::cout << "PASS" << std::endl;
std::cout << "Running TestIntMinTableDriven..." << std::endl;
TestIntMinTableDriven();
std::cout << "PASS" << std::endl;
std::cout << "Running BenchmarkIntMin..." << std::endl;
BenchmarkIntMin();
} catch (const std::exception& e) {
std::cerr << "Test failed: " << e.what() << std::endl;
return 1;
}
return 0;
}
To compile and run this C++ program:
$ g++ -std=c++11 -O2 test_intmin.cpp -o test_intmin
$ ./test_intmin
Running TestIntMinBasic...
PASS
Running TestIntMinTableDriven...
PASS
Running BenchmarkIntMin...
BenchmarkIntMin: 0 ns/op
This C++ version mimics the structure and functionality of the original Go example. Here are some key differences:
Instead of using a testing framework, we’ve implemented simple test functions that throw exceptions on failure.
The table-driven test uses a
std::vector
ofTestCase
structs instead of an anonymous struct slice.For benchmarking, we use the C++
chrono
library to measure execution time, as C++ doesn’t have a built-in benchmarking tool like Go does.Error reporting is done by throwing exceptions instead of using a testing.T object.
The main function runs all tests and the benchmark, whereas in Go these would typically be run by the
go test
command.
Remember that C++ doesn’t have a standard testing framework built into the language like Go does. In practice, you’d likely use a testing framework like Google Test or Catch2 for more comprehensive testing capabilities.