UnitTests

From OPeNDAP Documentation
⧼opendap2-jumptonavigation⧽

CppUnit basic layout

The example below shows a complete unit test written with CppUnit. Using the helper macros streamlines writing the tests.

When writing tests, make the default behavior as quiet as possible since the tests will likely be run by an automated build. Use a debug macro or switch to control output of instrumentation.

Running tests by name

To run a test by name, where 'test' means one of the methods in the TestFixture class, pass the method name to TestRunner::run(). For example, if you have a TestRunner named runner, a TestFixture class named MyTests and it has methods void test_1() {} and void test_2() {}, you would run those by calling runner.run("myTest::test_1") and runner.run(:myTes::test_2"). This will work if the test source file uses the macro CPPUNIT_TEST_SUITE( MyTest ); to declare the TestFixure and CPPUNIT_TEST(test_1);, ..., to declare the individual tests. Note that after the TestFixure class is defined, the macro CPPUNIT_TEST_SUITE_REGISTRATION(MyTest); must be used.

Using command line switches to control output

Look in the example to see how I use Gnu's GetOpt to process command line options. In the code, '-d' is used to turn on debugging. When on, a static global is set to true and a macro writes various instrumentation to stderr. Here's the global (file scope) and macro:

and the code to process the switch and call tests if they are named on the command line:

Putting it all together

#include "config.h"

#include <cppunit/TextTestRunner.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/extensions/HelperMacros.h>

#include <GetOpt.h> // Part of libdap

//#define DODS_DEBUG

#include "D4Dimensions.h"
#include "XMLWriter.h"

#include "Error.h"
#include "debug.h"

#include "testFile.h"
#include "test_config.h"

using namespace CppUnit;
using namespace std;
using namespace libdap;

static bool debug = false;

#undef DBG
#define DBG(x) do { if (debug) (x); } while(false);

class D4DimensionsTest: public TestFixture {
private:
    XMLWriter *xml;
    D4Dimensions *d;

public:
    D4DimensionsTest() {
    }

    ~D4DimensionsTest() {
    }

    void setUp() {
        d = new D4Dimensions;
        xml = new XMLWriter;
    }

    void tearDown() {
        delete xml;
        delete d;
    }

    void test_print_copy_ctor() {
        d->add_dim_nocopy(new D4Dimension("first", 10));
        d->add_dim_nocopy(new D4Dimension("second", 100));
        d->add_dim_nocopy(new D4Dimension("third"));

        D4Dimensions lhs(*d);

        lhs.print_dap4(*xml);
        string doc = xml->get_doc();
        string baseline = readTestBaseline(string(TEST_SRC_DIR) + "/D4-xml/D4Dimensions_3.xml");
        DBG(cerr << "test_print_copy_ctor: doc: " << doc << endl);
        DBG(cerr << "test_print_copy_ctor: baseline: " << baseline << endl);
        CPPUNIT_ASSERT(doc == baseline);
    }

    CPPUNIT_TEST_SUITE( D4DimensionsTest );

        CPPUNIT_TEST(test_print_empty);

        // CPPUNIT_TEST_EXCEPTION( test_error, Error );
 
    CPPUNIT_TEST_SUITE_END();
};

CPPUNIT_TEST_SUITE_REGISTRATION(D4DimensionsTest);

int main(int argc, char*argv[]) {
    CppUnit::TextTestRunner runner;
    runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());

    GetOpt getopt(argc, argv, "d");
    char option_char;

    while ((option_char = getopt()) != EOF)
        switch (option_char) {
        case 'd':
            debug = 1;  // debug is a static global
            break;
        default:
            break;
        }

    bool wasSuccessful = true;
    string test = "";
    int i = getopt.optind;
    if (i == argc) {
        // run them all
        wasSuccessful = runner.run("");
    }
    else {
        while (i < argc) {
            test = string("D4DimensionsTest::") + argv[i++];

            wasSuccessful = wasSuccessful && runner.run(test);
        }
    }

    return wasSuccessful ? 0 : 1;
}