Assertions
- The goals when writing the new assertions facility were to:
- make it easier to write custom assertions (specifically, being able to write complex assertions by reusing simple ones, support for default values in arguments)
- decouple customization of conversion to string and equality comparison in equality assertions
- provide more flexibility in customization of conversion to string and equality comparison
- allow string types to be decorated with "..." so whitespace can be seen
- provide string-specific assertions
- provide some support for string types other than std::string. Two alternative designs were implemented and experimented with before electing the second one the winner.
Here is how an assertion is written with CppUnit2:
# define CPPUT_ASSERT \
CPPUT_BEGIN_ASSERTION_MACRO() \
::CppUT::checkTrue
void checkTrue( bool shouldBeTrue, const Message &message )
{
if ( shouldBeTrue )
return;
Message newMessage( message );
newMessage.insertAt( 0, translate( "Assertion failed: expression did not evaluate to true." ) );
fail( newMessage );
}- The CPPUT_ASSERT macro first captures the location of the assertion (file, line...) with CPPUT_BEGIN_ASSERTION_MACRO() and then forwards the call to the function checkTrue() which implements the assertion. The final call to fail() will actually throw the assertion exception, using the location that was previously captured. This idiom supports overloading, default parameter values and templatized assertion functions, and conversion of macro parameters to strings (for insertion in messages) is still possible.
Note: currently investigating the possibility of capturing the call stack in addition to the file and source line.
- Here is a list of the assertions provided. The names should speak for themselves:
- Basic assertions
- CPPUT_ASSERT
- CPPUT_ASSERT_EXPR( expression )
- CPPUT_ASSERT_FALSE
- CPPUT_ASSERT_EXPR_FALSE( expression )
- CPPUT_ASSERT_EQUAL
- CPPUT_ASSERT_NOT_EQUAL
CPPUT_ASSERT_THROW( expression, ExceptionType )
- CPPUT_ASSERT_NO_THROW( expression )
- CPPUT_ASSERT_ASSERTION_FAIL( assertion )
- CPPUT_ASSERT_ASSERTION_PASS( assertion )
- Assertions working with string
- CPPUT_ASSERTSTR_START
- CPPUT_ASSERTSTR_END
- CPPUT_ASSERTSTR_CONTAIN
- CPPUT_ASSERTSTR_EQUAL
- Enumeration assertions
- CPPUT_ASSERT_SEQUENCE_EQUAL
- CPPUT_ASSERT_SET_EQUAL
- CPPUT_ASSERT_STL_SEQUENCE_EQUAL
- CPPUT_ASSERT_STL_SET_EQUAL
The new assertions working with strings introduced another service: conversion of a string type to an std::string. This allows the testing framework to work with unknown string type, as long as the user provides the required conversion functions. Those assertions will always convert their string arguments to std::strings before proceeding with the assertion test. This allows testing of two const char * pointers for equality as strings instead of pointers. The conversion of objects to strings will recognize string types and automatically escape and quote them. No more chasing non-printable characters on equality failure messages. Customization is done completely within headers and can therefore be done on a per-translation unit/application basis.
Note: some regular-expression-based assertions would be useful.