Home CS 5201

CS 5201: Unit Testing

Unit testing is a fantastic way to write bug-free code and to keep your code bug-free, even in big codebases. At S&T, you have at least three choices for unit test frameworks: Catch2, GTest, and Boost UTF.

Regardless of your choice, I recommend providing a test target in your makefile so you can simply run make test to build and run your unit tests. Also, make sure that make clean cleans up any object files your unit tests produce.

Catch2

Catch2 is a header-only unit test framework, so you can just download the header file, include it, and you're good to go. It has a different take on testing from how Boost and GTest work; it's similar to RSpec, if you know that tool. Most significantly, it doesn't use test fixtures—it has a different means of achieving the same functionality.

I find Catch2 to be much easier to use than Boost or GTest style testing. It also is designed to have more understandable compiler errors.

Take a look at the tutorial to get started and the reference for all the details. Furthermore, chapter 11 of the CS 1001 Lab Book covers Catch, and will be updated to Catch2 shortly.

GTest / Google Test

Google provides a unit testing framework that is generally considered to be very easy to use. The best way to get started is to read their Primer. They also provide some documentation.

Note that Google's documentation shows #include "gtest/gtest.h"; however, GTest is installed in a standard place on the campus machines, so you should #include <gtest/gtest.h> instead.

Using GTest on the campus machines is a little unusual, since Google does not provide binaries, only source. The GTest source is located at /usr/src/gtest. Fortunately, compiling this is easy and can be incorporated into your makefile; see an example. The example makefile builds GTest in a gtest subfolder—naturally, you shouldn't include any of that compiled junk when you submit!

Boost UTF

Boost contains a unit test framework (UTF), because of course it does. The documentation is detailed, if a bit daunting. I found this tutorial handy for getting started. There's also my CS 1001 slides that go along with the example code.

The general gist of unit testing with Boost is that you have a pile of assertions that check that various things are equal, not equal, etc. (There are also assertions for comparing floating point values and for verifying that exceptions are or aren't thrown.) Boost has three levels of asserts: WARN, which prints a message; ERROR, which prints an error, but keeps testing; and REQUIRE, which prints an error and halts the test.

These assertions are used by test cases, which are functions that each test one small part of your program. You can organize test cases into test suites; it's generally good to make a test suite for each class. I recommend making a test_classname.cpp file for each class so your tests are easy to find.

If you're testing a class, you'll commonly want to make up some instances of that class that each test case can use. Boost offers a Test Fixture feature that configures code to be run before and after each test case. That code can set up objects that your test cases can then use without needing to repeat the setup code in each test case.

In your individual test cpp files, I recommend you include just the prototypes for the UTF by using #include<boost/test/unit_test.hpp>. Then, make a test_main.cpp file that includes the UTF implementation; see the example code. This dramatically shortens the compile time for your tests!