Personal tools
You are here: Home Documentation 1-0pre1 V1.0pre1

Class Black Box Testing
[Concepts]

To provide a maximum reliability for all BN++ classes, each class provides its own test program to ensure that each class compiles and behaves (at least basically) as intended. More...

Files

file ClassTest.h
Macros used by the test programs in the subdirectory BNPP/source/TEST.

Defines

#define PRECISION(a) TEST::precision = (a);
Define the precision for floating point comparisons.
#define START_TEST(class_name, version)
Create the test header for a certain class.
#define END_TEST
Termination of test program.
#define RESULT
Check subtest result.
#define TEST_REAL_EQUAL(a, b)
Floating point equality macro.
#define TEST_EQUAL(a, b)
Generic equality macro.
#define TEST_NOT_EQUAL(a, b)
Generic inequality macro.
#define TEST_EXCEPTION(exception_type, command)
Exception test macro.
#define ABORT_IF(condition) if (condition) break;
Skip remainder of subtest.
#define TEST_FILE(filename, templatename)
File comparison macro.

Detailed Description

To provide a maximum reliability for all BN++ classes, each class provides its own test program to ensure that each class compiles and behaves (at least basically) as intended.

The testprograms reside in the directory source/TEST, they may be built and executed by calling make test.

Each test program prints after execution either "PASSED" or "FAILED". If any of the subtest contained in the test program fails, the whole test failed. The result of the test program can also be checked via its exit code. An exit code of zero means "PASSED", non-zero exit code means "FAILED".

There are several macros defined to simplify the creation of a test program and to provide a common interface. Each test program consists of several subtests which usually test one method or property of the class. Each of this subtests uses a series of elementary tests to check the functionality of the method.

A number of elementary tests has been implemented that is sufficient for most cases:

  • TEST_EQUAL
  • TEST_NOT_EQUAL
  • TEST_REAL_EQUAL A subtest is defined by calling the CHECK macro with the subtest name as an argument. Then a series of calls to TEST macros follows, mixed with standard BN++ code (remember to include all neccessary header files). The subtest is terminated by calling RESULT . Use the two macros START_TEST and END_TEST to generate a complete test program.

To create a new test program, use the file source/TEST/Skeleton_test.C


Define Documentation

#define ABORT_IF ( condition ) if (condition) break;

Skip remainder of subtest.

If the condition is not fulfilled, the remainder of the test is skipped. The status (whether it fails or passes) remains unchanged.

\

#define END_TEST

Termination of test program.

This macro implements the correct termination of the test program and should therefore be the last macro to call. It determines the exit code based on all previously run subtests and prints out the message "PASSED" or "FAILED". This macro also closes the global try block opened by START_TEST and contains the related catch clauses. If an exception is caught here, the test program fails.

\

#define PRECISION ( a ) TEST::precision = (a);

Define the precision for floating point comparisons.

The macro TEST_REAL_EQUAL checks whether the floating point number returned by the subtest is close to the expected result by comparing the absolute value of the difference of the two values to PRECISION.

The default value is $10^{-6}$. It is possible to redefine precision in the test program by calling this macro with the new value.

#define RESULT

Check subtest result.

Each elementary test macro updates an internal variable (TEST, defined by START_TEST ) that holds the state of the current subtest.

RESULT prints whether the subtest has failed or passed in verbose mode and updates the internal variables TEST::all_tests that describes the state of the whole class test. TEST::all_tests is initialized to be true. If any elementary test fails, TEST::test becomes false. At the time of the next call to RESULT, TEST::all_tests will be set to false, if TEST::test is false. One failed elementary test leads therefore to a failed subtest, which leads to a failed class test.

This macro closes the try block opened by CHECK, so CHECK and RESULT have to be balanced, or some ugly compile-time errors may occur. RESULT first tries to catch all BNPP exceptions (i.e. exceptions derived from Exception::Base). If this fails, it tries to catch any exception. After the exception is thrown, the execution will continue with the next subtest, the current subtest will be marked as failed (as is the whole test program).

\

#define START_TEST ( class_name,
version )

Create the test header for a certain class.

This macro defines the start of the test program for a given classname. The classname is printed together with some information when calling the test program with any arguments (except for -v or -V).

This macro should be the first to call in a test program. It introduces a global try block to catch any unwanted exceptions. If any of these exceptions occurs, all tests failed. Exceptions defined by BNPP (i.e. exception classes derived from Exception::Base) provide some additional information that is evaluated by the END_TEST macro. The END_TEST macro also closes the try block. This try block should never catch an exception! All exceptions that are thrown due to some malfunction in one of the member functions should be caught by the try block created by CHECK and RESULT.

#define TEST_EQUAL ( a,
b )

Value:

{\
    TEST::this_test = ((a) == (b));\
    TEST::test = TEST::test && TEST::this_test;\
    if ((TEST::verbose > 1) || (!TEST::this_test && (TEST::verbose > 0)))\
    {\
      if (!TEST::newline)\
      {\
        TEST::newline = true;\
        std::cout << std::endl;\
      }\
      std::cout << "    (line " << __LINE__ << " TEST_EQUAL(" << #a << ", " << #b << "): got " << (a) << ", expected " << (b) << ") ";\
      if (TEST::this_test)\
        std::cout << " + " << std::endl;\
      else \
        std::cout << " - " << std::endl;\
    }\
  }\
Generic equality macro.

This macro uses the operator == to check its two arguments for equality. Besides handling some internal stuff, it basically evaluates #((a) == (b))#.

Remember that operator == has to be defined somehow for the two argument types.

Parameters:
a value/object to test
b expected value
\
#define TEST_EXCEPTION ( exception_type,
command )

Exception test macro.

This macro checks if a given type of exception occured while executing the given command. Example:

#TEST_EXCEPTION(Exception::IndexOverflow,
vector3[-1])#
If no or a wrong exception occured, false is returned,
otherwise true.
Parameters:
exception_type the exception-class
command any general C++ or BNPP-specific command
\
#define TEST_FILE ( filename,
templatename )

File comparison macro.

This macro is used to test file operations. It compares the file with name filename against a template file templatename. Corresponding lines of the two files have to be identical.

See also:
TEST_FILE_REGEXP for more sophisticated comparisons
Note:
line length is limited to 64k characters
\
#define TEST_NOT_EQUAL ( a,
b )

Value:

{\
    TEST::this_test = !((a) == (b));\
    TEST::test = TEST::test && TEST::this_test;\
    if ((TEST::verbose > 1) || (!TEST::this_test && (TEST::verbose > 0)))\
    {\
      if (!TEST::newline)\
      {\
        TEST::newline = true;\
        std::cout << std::endl;\
      }\
      std::cout << "    (line " << __LINE__ << " TEST_NOT_EQUAL(" << #a << ", " << #b << "): got " << (a) << ", forbidden is " << (b) << ") ";\
      if (TEST::this_test)\
        std::cout << " + " << std::endl;\
      else \
        std::cout << " - " << std::endl;\
    }\
  }\
Generic inequality macro.

This macro checks for inequality as TEST_EQUAL tests for equality. The only difference between the two macros is that TEST_NOT_EQUAL evaluates #!((a) == (b))#.

Parameters:
a value/object to test
b forbidden value
\
#define TEST_REAL_EQUAL ( a,
b )

Value:

TEST::this_test = (fabs((double)(a) -  (double)(b)) < TEST::precision); \
  TEST::test = TEST::test && TEST::this_test;\
  if ((TEST::verbose > 1) || (!TEST::this_test && (TEST::verbose > 0)))\
  {\
    if (!TEST::newline)\
    {\
      TEST::newline = true;\
      std::cout << std::endl;\
    }\
    std::cout << "    (line " << __LINE__ << " TEST_REAL_EQUAL("<< #a << ", " << #b << "): got " << (a) << ", expected " << (b) << ") ";\
    if (TEST::this_test)\
      std::cout << " + " << std::endl;\
    else \
      std::cout << " - " << std::endl;\
  }\
Floating point equality macro.

Checks whether the absolute value of the difference of the two floating point values a and b is less or equal to the value defined by PRECISION.

Parameters:
a floating point value to test
b expected value
\