|
Simbody 3.9
|
SimTK defines some utilities to facilitate the creation of regression tests for SimTK facilities. More...
Classes | |
| class | SimTK::Test |
| This is the main class to support testing. More... | |
| class | SimTK::Test::Subtest |
| Internal utility class for generating test messages for subtests. More... | |
Macros | |
| #define | SimTK_START_TEST(testName) |
| Invoke this macro before anything else in your test's main(). | |
| #define | SimTK_END_TEST() |
| Invoke this macro as the last thing in your test's main(). | |
| #define | SimTK_SUBTEST(testFunction) do {SimTK::Test::Subtest sub(#testFunction); (testFunction)();} while(false) |
| Invoke a subtest in the form of a no-argument function, arranging for some friendly output and timing information. | |
| #define | SimTK_SUBTEST1(testFunction, arg1) do {SimTK::Test::Subtest sub(#testFunction); (testFunction)(arg1);} while(false) |
| Invoke a subtest in the form of a 1-argument function, arranging for some friendly output and timing information. | |
| #define | SimTK_SUBTEST2(testFunction, arg1, arg2) do {SimTK::Test::Subtest sub(#testFunction); (testFunction)(arg1,arg2);} while(false) |
| Invoke a subtest in the form of a 2-argument function, arranging for some friendly output and timing information. | |
| #define | SimTK_SUBTEST3(testFunction, arg1, arg2, arg3) do {SimTK::Test::Subtest sub(#testFunction); (testFunction)(arg1,arg2,arg3);} while(false) |
| Invoke a subtest in the form of a 3-argument function, arranging for some friendly output and timing information. | |
| #define | SimTK_SUBTEST4(testFunction, arg1, arg2, arg3, arg4) do {SimTK::Test::Subtest sub(#testFunction); (testFunction)(arg1,arg2,arg3,arg4);} while(false) |
| Invoke a subtest in the form of a 4-argument function, arranging for some friendly output and timing information. | |
| #define | SimTK_TEST(cond) {SimTK_ASSERT_ALWAYS((cond), "Test condition failed.");} |
| Test that some condition holds and complain if it doesn't. | |
| #define | SimTK_TEST_FAILED(msg) {SimTK_ASSERT_ALWAYS(!"Test case failed.", msg);} |
| Call this if you have determined that a test case has failed and just need to report it and die. | |
| #define | SimTK_TEST_FAILED1(fmt, a1) {SimTK_ASSERT1_ALWAYS(!"Test case failed.",fmt,a1);} |
| Call this if you have determined that a test case has failed and just need to report it and die. | |
| #define | SimTK_TEST_FAILED2(fmt, a1, a2) {SimTK_ASSERT2_ALWAYS(!"Test case failed.",fmt,a1,a2);} |
| Call this if you have determined that a test case has failed and just need to report it and die. | |
| #define | SimTK_TEST_EQ(v1, v2) |
| Test that two numerical values are equal to within a reasonable numerical error tolerance, using a relative and absolute error tolerance. | |
| #define | SimTK_TEST_EQ_SIZE(v1, v2, n) |
| Test that two numerical values are equal to within a specified multiple of the default error tolerance. | |
| #define | SimTK_TEST_EQ_TOL(v1, v2, tol) |
| Test that two numerical values are equal to within a specified numerical error tolerance, using a relative and absolute error tolerance. | |
| #define | SimTK_TEST_NOTEQ(v1, v2) |
| Test that two numerical values are NOT equal to within a reasonable numerical error tolerance, using a relative and absolute error tolerance. | |
| #define | SimTK_TEST_NOTEQ_SIZE(v1, v2, n) |
| Test that two numerical values are NOT equal to within a specified multiple of the default error tolerance, using a relative and absolute error tolerance. | |
| #define | SimTK_TEST_NOTEQ_TOL(v1, v2, tol) |
| Test that two numerical values are NOT equal to within a specified numerical error tolerance, using a relative and absolute error tolerance. | |
| #define | SimTK_TEST_MUST_THROW(stmt) |
| Test that the supplied statement throws an std::exception of some kind. | |
| #define | SimTK_TEST_MUST_THROW_SHOW(stmt) |
| Test that the supplied statement throws an std::exception of some kind, and show what message got thrown. | |
| #define | SimTK_TEST_MUST_THROW_EXC(stmt, exc) |
| Test that the supplied statement throws a particular exception. | |
| #define | SimTK_TEST_MAY_THROW(stmt) |
| Allow the supplied statement to throw any std::exception without failing. | |
| #define | SimTK_TEST_MAY_THROW_EXC(stmt, exc) |
| Allow the supplied statement to throw a particular exception without failing. | |
| #define | SimTK_TEST_MUST_THROW_DEBUG(stmt) SimTK_TEST_MUST_THROW(stmt) |
| Include a bad statement when in Debug and insist that it get caught, but don't include the statement at all in Release. | |
| #define | SimTK_TEST_MUST_THROW_EXC_DEBUG(stmt, exc) SimTK_TEST_MUST_THROW_EXC(stmt,exc) |
| Include a bad statement when in Debug and insist that it get caught, but don't include the statement at all in Release. | |
SimTK defines some utilities to facilitate the creation of regression tests for SimTK facilities.
These utilities consist of a SimTK::Test class and related support macros.
Features include:
Here's how you use this facility:
#include "SimTKcommon.h"
void myFirstSubtest() {...}
void myNextSubtest() {...}
int main() {
SimTK_START_TEST("OverallTestName");
SimTK_SUBTEST(myFirstSubtest);
SimTK_SUBTEST(myNextSubtest);
SimTK_END_TEST();
}
The arguments to SimTK_SUBTEST are function names and will be called with "()" appended. If your subtest functions have arguments, use SimTK_SUBTEST1(name,arg) or SimTK_SUBTEST2(name,arg1,arg2) which will call name(arg) or name(arg1,arg2) as appropriate.
This will result in nice output including execution times for the overall test and the individual subtests, and arrange for any exceptions raised in the tests to be caught, properly reported, and cause a non-zero return from main(). If everything runs successfully, main() will return 0. Here is an example of the output produced:
Starting test TestScalar ... testIsNaN ... done. testIsNaN time: 0ms. testIsInf ... done. testIsInf time: 0ms. testIsFinite ... done. testIsFinite time: 0ms. testSignBit ... done. testSignBit time: 0ms. testSign ... done. testSign time: 0ms. testSquareAndCube ... done. testSquareAndCube time: 0ms. Done. TestScalar time: 15ms.
(Admittedly the timings aren't much use in that example!)
Within your subtests, several useful macros and static functions are available. By using these macros, the resulting message will include the actual line number at which the test failure occurred.
SimTK_TEST(cond) -- this is like assert(cond)
SimTK_TEST_FAILED("message") -- like assert(!"message")
SimTK_TEST_EQ(a,b) -- equal to within a default tolerance
SimTK_TEST_NOTEQ(a,b) -- not equal to within a default tolerance
SimTK_TEST_EQ_SIZE(a,b,n) -- equal to within n * default tolerance
SimTK_TEST_NOTEQ_SIZE(a,b,n) -- not equal to within n * default tolerance
SimTK_TEST_EQ_TOL(a,b,tol) -- same as above with specified tolerance
SimTK_TEST_NOTEQ_TOL(a,b,tol)
SimTK_TEST_MUST_THROW(statement) -- we expect the statement to throw some exception
SimTK_TEST_MUST_THROW_EXC(statement, exception) -- we expect a particular exception type
SimTK_TEST_MUST_THROW_DEBUG(statement) -- same as above but only checked in Debug builds
SimTK_TEST_MUST_THROW_EXC_DEBUG(statement, exception) -- ditto
#define SimTK_TEST_SUPPRESS_MUST_THROW
-- Define this temporarily at top of test programs to make it
easier to locate an *unexpected* exception while debugging. It
simply disables the "MUST_THROW" macros so you don't have to wade
through them in the debugger to get to the actual problem.
The SimTK_TEST_EQ macros test scalar and composite numerical values for equality to within a numerical tolerance, using both relative and absolute tolerances. The default is the value of SignificantReal for the underlying numerical type. For composite types the equality test is done elementwise; that is, we apply it strictly to each pair of elements not to an overall norm.
The SimTK_TEST_EQ_SIZE macros allows you to specify a multiple of default tolerance to be used. This is necessary for most Matrix operations since attainable accuracy falls off with the size of the matrix. Typically, if the smallest dimension of the Matrix is n, then the tolerance you should allow is n*scalarTol where scalarTol is the default tolerance for a scalar operation. Note that you still need to specify size when comparing Vector or scalar values if those values were produced using a matrix computation.
The SimTK_TEST_EQ_TOL macros take a user-specified tolerance value for the elementwise tests, overriding the default.
The SimTK::Test class has a number of static methods that are useful in tests. Currently these are all for generating numerical objects filled with random numbers (all uniform between -1 and 1). These are:
randReal() randFloat() randDouble()
randComplex() randConjugate()
randVec<M>() randRow<N>() randMat<M,N>() randSymMat<N>()
randVector(m) randMatrix(m,n)
randVec3() randMat33()
randSpatialVec() randSpatialMat()
randRotation() randTransform()
These are invoked Test::randReal() etc.
| #define SimTK_START_TEST | ( | testName | ) |
Invoke this macro before anything else in your test's main().
| #define SimTK_END_TEST | ( | ) |
Invoke this macro as the last thing in your test's main().
| #define SimTK_SUBTEST | ( | testFunction | ) | do {SimTK::Test::Subtest sub(#testFunction); (testFunction)();} while(false) |
Invoke a subtest in the form of a no-argument function, arranging for some friendly output and timing information.
| #define SimTK_SUBTEST1 | ( | testFunction, | |
| arg1 | |||
| ) | do {SimTK::Test::Subtest sub(#testFunction); (testFunction)(arg1);} while(false) |
Invoke a subtest in the form of a 1-argument function, arranging for some friendly output and timing information.
| #define SimTK_SUBTEST2 | ( | testFunction, | |
| arg1, | |||
| arg2 | |||
| ) | do {SimTK::Test::Subtest sub(#testFunction); (testFunction)(arg1,arg2);} while(false) |
Invoke a subtest in the form of a 2-argument function, arranging for some friendly output and timing information.
| #define SimTK_SUBTEST3 | ( | testFunction, | |
| arg1, | |||
| arg2, | |||
| arg3 | |||
| ) | do {SimTK::Test::Subtest sub(#testFunction); (testFunction)(arg1,arg2,arg3);} while(false) |
Invoke a subtest in the form of a 3-argument function, arranging for some friendly output and timing information.
| #define SimTK_SUBTEST4 | ( | testFunction, | |
| arg1, | |||
| arg2, | |||
| arg3, | |||
| arg4 | |||
| ) | do {SimTK::Test::Subtest sub(#testFunction); (testFunction)(arg1,arg2,arg3,arg4);} while(false) |
Invoke a subtest in the form of a 4-argument function, arranging for some friendly output and timing information.
| #define SimTK_TEST | ( | cond | ) | {SimTK_ASSERT_ALWAYS((cond), "Test condition failed.");} |
Test that some condition holds and complain if it doesn't.
| #define SimTK_TEST_FAILED | ( | msg | ) | {SimTK_ASSERT_ALWAYS(!"Test case failed.", msg);} |
Call this if you have determined that a test case has failed and just need to report it and die.
Pass the message as a string in quotes.
| #define SimTK_TEST_FAILED1 | ( | fmt, | |
| a1 | |||
| ) | {SimTK_ASSERT1_ALWAYS(!"Test case failed.",fmt,a1);} |
Call this if you have determined that a test case has failed and just need to report it and die.
The message is a printf format string in quotes; here with one argument expected.
| #define SimTK_TEST_FAILED2 | ( | fmt, | |
| a1, | |||
| a2 | |||
| ) | {SimTK_ASSERT2_ALWAYS(!"Test case failed.",fmt,a1,a2);} |
Call this if you have determined that a test case has failed and just need to report it and die.
The message is a printf format string in quotes; here with two arguments expected.
| #define SimTK_TEST_EQ | ( | v1, | |
| v2 | |||
| ) |
Test that two numerical values are equal to within a reasonable numerical error tolerance, using a relative and absolute error tolerance.
In the case of composite types, the test is performed elementwise.
| #define SimTK_TEST_EQ_SIZE | ( | v1, | |
| v2, | |||
| n | |||
| ) |
Test that two numerical values are equal to within a specified multiple of the default error tolerance.
| #define SimTK_TEST_EQ_TOL | ( | v1, | |
| v2, | |||
| tol | |||
| ) |
Test that two numerical values are equal to within a specified numerical error tolerance, using a relative and absolute error tolerance.
In the case of composite types, the test is performed elementwise.
| #define SimTK_TEST_NOTEQ | ( | v1, | |
| v2 | |||
| ) |
Test that two numerical values are NOT equal to within a reasonable numerical error tolerance, using a relative and absolute error tolerance.
In the case of composite types, the equality test is performed elementwise.
| #define SimTK_TEST_NOTEQ_SIZE | ( | v1, | |
| v2, | |||
| n | |||
| ) |
Test that two numerical values are NOT equal to within a specified multiple of the default error tolerance, using a relative and absolute error tolerance.
In the case of composite types, the equality test is performed elementwise.
| #define SimTK_TEST_NOTEQ_TOL | ( | v1, | |
| v2, | |||
| tol | |||
| ) |
Test that two numerical values are NOT equal to within a specified numerical error tolerance, using a relative and absolute error tolerance.
In the case of composite types, the equality test is performed elementwise.
| #define SimTK_TEST_MUST_THROW | ( | stmt | ) |
Test that the supplied statement throws an std::exception of some kind.
| #define SimTK_TEST_MUST_THROW_SHOW | ( | stmt | ) |
Test that the supplied statement throws an std::exception of some kind, and show what message got thrown.
| #define SimTK_TEST_MUST_THROW_EXC | ( | stmt, | |
| exc | |||
| ) |
Test that the supplied statement throws a particular exception.
| #define SimTK_TEST_MAY_THROW | ( | stmt | ) |
Allow the supplied statement to throw any std::exception without failing.
| #define SimTK_TEST_MAY_THROW_EXC | ( | stmt, | |
| exc | |||
| ) |
Allow the supplied statement to throw a particular exception without failing.
| #define SimTK_TEST_MUST_THROW_DEBUG | ( | stmt | ) | SimTK_TEST_MUST_THROW(stmt) |
Include a bad statement when in Debug and insist that it get caught, but don't include the statement at all in Release.
| #define SimTK_TEST_MUST_THROW_EXC_DEBUG | ( | stmt, | |
| exc | |||
| ) | SimTK_TEST_MUST_THROW_EXC(stmt,exc) |
Include a bad statement when in Debug and insist that it get caught, but don't include the statement at all in Release.