Monday, April 6, 2015

Parallelizing c++ boost unit test cases

Downloads

Source.zip

SampleApplication.zip ( Please update the boost include and lib paths in project settings. )

Alternate Download link

SampleApplicaiton.zip
Source.zip

In big projects, it is common to have thousands of unit test cases. In one of our projects we used boost framework for writing unit TCs and used to run all the TCs in build server after every check-in. The number of TCs eventually grew to thousands and it takes around 3, 4 hours to finish all the test cases. Even though our build server was running on a 32 core machine, we couldn't take advantage of it because boost's framework always run test cases in one thread. Running in multiple thread is not a generic solution as the testcases might be accessing some shared object that could cause synchronization issues. There is one alternate solution available via CMake which is describe in the post Run your Boost Tests in parallel with CMake . The only down side of this solution is that, you have to list down each testcase of your unit test application in the makefile. When we have thousands of test cases, it is not a very feasible solution. Then we started looked into the boost test framework and see if anything cane be done at the framework side.

Tweeking startup code

  • Supported OS: Windows and Unix - compatible OS
  • Tested on boost 1.47
This solution actually works with a slight modification in main function of boost test case. All you have to do is to include unit_test_main_parallel.hpp instead of boost/test/unit_test.hpp in your unit test case project.After building your unitestcase application, to run the testcases in parallel simply add the option "--dist_tc="

For eg:
c:\Naveen\tmp>UnitTestApp.exe --dist_tc=5
The above command will start one parent UnitTestApp.exe and 5 child UnitTestApp.exe , each executing one test case at a time. Here is how it looks in process explorer.



Once a child application finishes the unit test case assigned to it, the child process exit by itself and another child application is spooled by the parent to execute the next TC. Please note that this option is incompatible with --run_test option. if --run_test is specified, --dist_tc option will be ignored.

Under the Hood

Underlying implementation is actually quite simple. 
  1. When application starts, it traverse though all test case in the application and create a list of test cases. 
  2. For each test case in the list, invoke child process with an additional --run_test option specifying the test case name.
  3. Redirect the console output of child process back to the parent application and print it.

Files

There are 3 files in this source
  • unit_test_main_parallel.hpp - Main header file that you need to include.
  • unit_test_main_unix.ipp - unix specific code.
  • unit_test_main_win.ipp - windows specific code.

Since Windows doesn't support POSIX API's, I had to write separate implementation for windows OS's. The unit_test_main_parallel.hpp will choose one of the .ipp file depending the platform in which it is getting compiled.