This wiki is obsolete, see the NorduGrid web pages for up to date information.

Unit Testing

From NorduGrid
Jump to navigationJump to search

Unit testing

We use CppUnit to do unit testing of ARC software components. The building and running of the tests are integrated in the autotools build procedure. The tests are also run during the nightly builds. This page summarizes the steps needed to add new tests to the ARC source tree. For actual examples see the already available tests, e.g. the tests of the URL class in libarccommon (src/hed/libs/common/test).

Test directory

The unit tests should reside in a sub-directory called "test".

mkdir test

This directory should be added to the SUBDIRS in the Makefile.am

SUBDIRS = ... $(TEST_DIR)
DIST_SUBDIRS = ... test

The variable $(TEST_DIR) is substituted via configure and is normally set to "test" unless cppunit is not found in which case it is empty,

Main test program

The main test program is the same for all tests. It is located at src/Test.cpp looks roughly like this:

#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>

int main() {
  CppUnit::TextUi::TestRunner runner;
  runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());

  runner.setOutputter(CppUnit::CompilerOutputter::defaultOutputter
                      (&runner.result(), std::cerr));

  bool wasSuccessful = runner.run();

  return wasSuccessful ? 0 : 1;
}

Makefile.am

The Makefile.am should declare the variables TESTS and check_PROGRAMS (this is using libname as an example - use the name of the library you are writing tests for). Each test should include the main test program in the sources list.

TESTS = libnametest
check_PROGRAMS = $(TESTS)

libnametest_SOURCES = $(top_srcdir)/src/Test.cpp Class1Test.cpp Class2Test.cpp ...
libnametest_CXXFLAGS = $(CPPUNIT_CFLAGS) ...
libnametest_LDADD = $(CPPUNIT_LIBS) ../liblibname.la ...

Test class

A test class can be based on the following template. The test program can contain more than one test class.

#include <cppunit/extensions/HelperMacros.h>

#include ... // the class you are writing the tests for
#include ... // whatever else you need

class Class1Test : public CppUnit::TestFixture {
  CPPUNIT_TEST_SUITE(Class1Test);
  CPPUNIT_TEST(Test1);
  CPPUNIT_TEST(Test2);
    .
    .
  CPPUNIT_TEST_SUITE_END();

 public:
  void setUp();     // optional
  void tearDown();  // optional

  void Test1();
  void Test2();
    .
    .

 private:
  // any member variables you need
};

void Class1Test::setUp() {
  // This is optional. If not defined the noop in the parent class will be used
  // Initialize any members that requires it
}

void Class1Test::tearDown() {
  // This is optional. If not defined the noop in the parent class will be used
  // Destroy any members that requires it
}

void Class1Test::Test1() {
  // do anything you need to compute a testable thing then use the test macros
  CPPUNIT_ASSERT(somestring.empty());
  CPPUNIT_ASSERT_EQUAL(expectedvalue, somevar);
  // For more complicated test macros see the CppUnit documentation
}

void Class1Test::Test2() {
  // Same principle as above - but test something different
}

  .
  .

CPPUNIT_TEST_SUITE_REGISTRATION(Class1Test);

Build and run

To build and run the tests do

make check

To help debug a failing test it can be run directly with the -v option which enables DEBUG level logging in the ARC code the test uses, e.g.

./test/MyTest -v