[cppx] A simple unit tests framework

I’m doing the cppx library development in Visual Studio 7.1. Each module has one or more unit tests, where each test is a program or header file, and the way Visual Studio works, in the cppx “solution” one would normally need to have a separate “project” for each test program. I’ve found that to be Very Annoying (to say the least) so I put all of it, all the tests, in one project, with the main routine calling various tests depending on preprocessor symbols.

Before main there are includes for the tests that are just header files, such as testing static assert functionality (it wouldn’t do to have such a test causing the whole test suite to fail compilation every time!), but for the each-a-logical-program tests main invokes them like:

#include <progrock/testing/macros.h>

int main()
{
    TESTING_SIMPLE_TEST( TEST_ARGUMENT_FORWARDING,  testArgumentForwarding  );
    TESTING_SIMPLE_TEST( TEST_CHAR_UTIL,            testCharUtil            );
    TESTING_SIMPLE_TEST( TEST_CLONING_UTIL,         testCloningUtil         );
    TESTING_SIMPLE_TEST( TEST_COUNTINGREF,          testCountingRef         );
    TESTING_SIMPLE_TEST( TEST_CSI,                  testCSI                 );
    TESTING_SIMPLE_TEST( TEST_DEBUGGER_API,         testDebuggerApi         );
    TESTING_SIMPLE_TEST( TEST_DEBUGGING,            testDebugging           );
    TESTING_SIMPLE_TEST( TEST_FIXED_SIZE_TYPES,     testFixedSizeTypes      );
    TESTING_SIMPLE_TEST( TEST_IT,                   testIt                  );
    TESTING_SIMPLE_TEST( TEST_ITERATOR_RANGE_UTIL,  testIteratorRangeUtil   );
    TESTING_SIMPLE_TEST( TEST_OPTIONS,              testOptions             );
    TESTING_SIMPLE_TEST( TEST_OWNERSHIP,            testOwnership           );
    TESTING_SIMPLE_TEST( TEST_REFCOUNTED,           testRefCounted          );
    TESTING_SIMPLE_TEST( TEST_SHARED,               testShared              );
    TESTING_SIMPLE_TEST( TEST_TYPECHECKING,         testTypechecking        );
    TESTING_SIMPLE_TEST( TEST_TYPELIST,             testTypelist            );
}

This, by the way, shows what cppx is mostly about: very basic, fundamental functionality.

In order to be able to run several tests in one go any number of the preprocessor symbols may be defined, as just about anything.

The magic that invokes the specified test routine depending on whether a preprocessor symbol is defined:

// f is called if preprocessor symbol &rsquo;symbol&rsquo; is defined.
// If &rsquo;symbol&rsquo; is defined it must be defined as nothing or as something
// that&rsquo;s valid at the end of a C++ name, e.g. TEST_BLAH defined as 1.
//
// Quirk: f will be called if e.g. TEST_BLAH is defined as TEST_BLAH.

#define TESTINGi_CALL_IFDEF_( symbol, literal_symbol, f, args )  \
    do {                                                        \
        struct S_##f {                                          \
            struct Size2 { char x[2]; };                        \
            char foo##literal_symbol( ... )  { return 0; }      \
            Size2 foo_##symbol( int ) { return Size2(); }       \
        };                                                      \
        if(                                                     \
            sizeof( S_##f().foo##literal_symbol(0) ) == 1       \
            )                                                   \
        { f args; }                                             \
    } while( false )

#define TESTING_CALL_IFDEF( symbol, f, args )   \
    TESTINGi_CALL_IFDEF_( symbol, _##symbol, f, args )

#define TESTING_SIMPLE_TEST( symbol, f )                        \
    extern void f();                                            \
    TESTINGi_CALL_IFDEF_( symbol, _##symbol, f, () )

One nice feature is that this allows allows a separate unit test GUI to only know about the macro symbols and a directory containing batch files for building and running tests. In the GUI (a simple Python program) I just select a test in a listbox. A possible drawback is how well it scales, or not, to larger projects, but so far it’s not been a problem.

🙂

Advertisements

2 comments on “[cppx] A simple unit tests framework

  1. Yes, you’re not the first to ask, Ian Collins also asked (but in reply to the hello world posting as I recall). I haven’t used Google’s unit testing but it apparently does not support testing of e.g. a static assert facility, or other cases where the code should fail compilation. Since my experience with modern C++ unit testing frameworks is limited I asked about this feature in [comp.lang.c++], and it seems that there’s no such. Anyway, the testing requirements for what I do are limited, I’d like to avoid dependencies on large frameworks or libraries, and the scheme I’m using is simple, small, explicit and very effective. 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s