Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Minimal unit test library for C++

0.00/5 (No votes)
4 Mar 2005 1  
Very small (one header) tool to support unit tests in C++

Introduction

Minitest is library to help with unit testing. It provides very small set of features (one macro, two functions):
  • macro (MINITEST) to define a test
  • execute all tests, in random order (to uncover possible dependencies between the tests)
  • execute only tests from last modified source files (to shorten the edit - compile - test cycle)

Example of use:

#include <minitest.hpp>

#include <assert.h>


#ifndef NDEBUG

MINITEST
{
   assert(...);
} 

MINITEST
{
  ...
  assert(...);
  assert(...);
}

#endif //!NDEBUG


int main()
{
  minitest::execute_all_tests(); // execute all tests in random order

}

The tests could be put in many translation units (*.cpp files).

Background

There are quite a few of C++ test frameworks (for overview see e.g. here). The library presented here doesn't offer as many features as others with hope it will be useable without much of learning and will be modifiable easily.

The library could be used when adding *.cpp files of large framework is not possible, as first step in creating battery of tests before going with large framework or to create second, independent set of tests for an application.

Using the code

Create test case:

#include <minitest.hpp>


#ifdef DO_TESTING

// create test(s) on top level in *.cpp file (i.e. not within function)

MINITEST
{
  AClass object; // can be created?

} 

MINITEST
{
  if (pDatabase) {
    pDatabase->do_internal_test();    
  } else {
    assert(false);
  }
}
#endif //DO_TESTING

There's only one macro - definition of test. To do actual checking use assert() or debug tools of your preference.

Execute all tests:

Function minitest::execute_all_tests(bool) runs the tests in random or fixed order and returns information how many tests passed and details about possible faulty one (for details see structure minitest::result in header).

#include <iostream>

#include <minitest.hpp>


int main() 
{
   // run all tests in random order

   minitest::execute_all_tests(); 

   // run all tests in the same order as before 

   // (e.g. if a failure happens and we want to repeat it)

   minitest::execute_all_tests(false); 
   
  // run all tests (randomly) and evaluate result

  minitest::result res = minitest::execute_all_tests();
  if (res.all_tests_succeeded) 
  {
    std::cout << "All " << res.sucessful_tests_count << " tests OK.\n";
  } 
  else 
  {
    std::cout << "Only first " << res.sucessful_tests_count << " test(s) OK\n"
              << "The test in file " << res.failed_test_file << ", line " 
              << res.failed_test_line << " threw an exception.\n";
    // failed test can re re-run again

    res.failed_test();
  }
}

Random order of execution:

rand() is used (internally by std::random_shuffle()) to simulate randomness of testing. In order to repeat the same sequence of tests do one of following

  • call minitest::execute_all_tests(false) and no randomization will be done - last order of execution is preserved
  • set and remember seed for random generator (by srand()) and set it again when needed

Execute only tests from last changed sources:

If running the test takes too long you may wish to run just those that were affected by recent changes in source code. The library provides support for this:

#include <minitest.hpp>


int main() 
{
  // execute tests from 3 source files modified last

  minitest::result res = minitest::test_last_changed_files(3);
  if (res.all_tests_succeeded) {
    // as before

  }
}

The library checks timestamp of all source files, selects the N files modified last and executes only tests from these. This should help to speed up edit-compile-test cycle and keep one in flow.

However running all the tests should be done from time to time: dependecies between modules are not handled here!

Dealing with DLLs:

Calling minitest::execute_all_functions() in main() will not run tests in DLLs. You need to add helper function, like:

// pseudocode
void complete_app_test() 
{
  minitest::execute_all_tests(); // in main executable
  foreach( just_loaded_DLLs ) {
    invoke_execute_all_tests( a_dll );
  }
}

int main() 
{
  complete_app_test();
}

This nuisance is due to header-only implementation of the library.

Dependencies and portability

STL is required. The library uses couple of headers from Boost. If needed, these headers can be replaced with short hand-coded equivalent.

The library was tested with VC6, BCB6 and Intel C++. I expect it to work under Posix systems as well.

History

  • March 2nd, 2005: version 1.0 submitted

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here