Constriants¶
The Verify() function¶
An assertion is made by a call to the Verify() function with a value as the first argument and a constraint on that value as the second argument. “Value” is meant to be taken in a wide sense since it may in some cases be a pointer to a function. An optional third argument may be given to include a custom error message. This message will be included in the test report if the test fails.
There is also a short form of the Verify() function, taking only one argument. This argument may be an expression but it must be possible to cast the result to bool.
// A typical call.
Verify(MyValue, SomeConstraint);
// It may also includes a custom error message
Verfify(MyValue, SomeConstraint, "My custom error message");
// Short form
Verify(MyValue == SomeValue);
// Short form with custom error message.
Verify(MyValue == SomeValue, "My custom error message");
The short form is handy if one which to fail a test for some reason.
// This will always fail.
Verify(false, "Test not implemented");
Constraints are functors, i.e. objects with the function call operator defined. They take one argument of same type as the value to verify and returns true if the value fulfills the constraint. If the constraint is not fulfilled by the value it throws a x_test_failed exception.
Verify() and its alias VERIFY() are actually macros and will expand to a call to the verify() function. There is no magic in there however, the macro will only add the current file and line to the call, i.e.
// This macro call
Verify(MyValue, SomeConstriant);
// will expand to
verify(__FILE__, __LINE__, MyValue, SomeConstraint);
There is a rich set of predefined constraints. Below follows a list of them and their syntax. Many constraints exist in an inverse form, which of course verifies the inverse constraint. Existence of an inverse form is marked with “(inv)” in the list.
Value constraints¶
- True
Check if a value is true.
Verify(MyValue, Is.True);
- False
Check if a value is false.
Verify(MyValue, Is.False);
- Null (inv)
Check if a value is NULL. This constraint is only defined for pointer types.
Verify(MyPointer, Is.Null); // Inverse form Verify(MyPointer, Is.Not.Null);
- NaN (inv)
Check if a value is not-a-number. This check uses the numeric_limits template for the type of the given value.
Verify(MyValue, Is.NaN); // Inverse form Verify(MyValue, Is.Not.NaN);
- NegativeInfinity (inv)
Check if a value is negative infinity. This check uses the numeric_limits template for the type of the given value.
Verify(MyValue, Is.NegativeInfinity); // Inverse form Verify(MyValue, Is.Not.NegativeInfinity);
- PositiveInfinity (inv)
Check if a value is positive infinity. This check uses the numeric_limits template for the type of the given value.
Verify(MyValue, Is.PositiveInfinity); // Inverse form Verify(MyValue, Is.Not.PositiveInfinity);
- Infinity (inv)
Check if a value is either positive or negative infinity. This check uses the numeric_limits template for the type of the given value.
Verify(MyValue, Is.Infinity); // Inverse form Verify(MyValue, Is.Not.Infinity);
- LessThan (inv)
Check if a value is less than a given value.
Verify(MyValue, Is.LessThan(Limit)); // Inverse form Verify(MyValue, Is.Not.LessThan(Limit));
- LessThanOrEqualTo (inv), AtMost
Check if a value is less than or equal to a given value.
Verify(MyValue, Is.LessThanOrEqualTo(Limit)); Verify(MyValue, Is.AtMost(Limit)); // Inverse form Verify(MyValue, Is.Not.LessThanOrEqualTo(Limit));
- EqualTo (inv)
Check that a value is equal to another value.
Verify(MyValue, Is.EqualTo(SomeValue)); // Inverse form Verify(MyValue, Is.Not.EqualTo(SomeValue));
- GreaterThanOrEqualTo (inv), AtLeast
Check if a value is greater than or equal to a given value.
Verify(MyValue, Is.GreaterThanOrEqualTo(Limit)); Verify(MyValue, Is.AtLeast(Limit)); // Inverse form Verify(MyValue, Is.Not.GreaterThanOrEqualTo(Limit));
- GreaterThan (inv)
Check if a value is greater than a given value.
Verify(MyValue, Is.GreaterThan(Limit)); // Inverse form Verify(MyValue, Is.Not.GreaterThan(Limit));
- SameAs (inv)
Check if a two instances are the same, useful for pointers and references.
Verify(MyReference, Is.SameAs(SomeReference)); // Inverse form Verify(MyReference, Is.Not.SameAs(SomeReference));
- InRange (inv)
Check that a value lies between two other values. The default is to include points on the boundery.
Verify(MyValue, Is.InRange(Low, High)); // Inverse form Verify(MyValue, Is.Not.InRange(Low,High));
- Within (inv)
Check that a value is within a symmetric interval around some given value. The interval may be given in either percent or in absolute units.
Verify(MyValue, Is.Within(p).PercentOf(SomeValue)); Verify(MyValue, Is.Within(u).UnitsOf(SomeValue)); // Inverse form Verify(MyValue, Is.Not.Within(p).PercentOf(SomeValue)); Verify(MyValue, Is.Not.Within(u).UnitsOf(SomeValue));
- CloseTo
CloseTo is a short form of Within(1e-6).UnitsOf(SomeValue), mostly for floating point comparison. If a different limit is desired this can be changed by setting the Limit property on the CloseTo object in e.g. the suite setup method.
// Change limit, in e.g. suite_setup CloseTo.Limit = 1e-3; // statement in some test method Verify(MyValue, Is.CloseTo(SomeValue));
- Constrained (inv)
Used for custom constraints with no arguments. The custom operation is supplied with the Using() method. It must be a functor taking one argument and returning true or false depending on if the value fulfills the operation or not
Verify(MyValue, Is.Constrained.Using(MyFunctor)); // Inverse form Verify(MyValue, Is.Not.Constrained.Using(MyFunctor));
- RelatedTo (inv)
Used for custom constraints with one argument. The custom operation is supplied with the Using() method. It must be a functor taking two arguments and returning true or false depending on if the two values fulfills the relation or not.
Verify(MyValue, Is.RelatedTo(SomeValue).Using(MyRelationFunctor)); // Inverse form Verify(MyValue, Is.Not.RelatedTo(SomeValue).Using(MyRelationFunctor));
This could for example be used for string matching using regular expressions. Assume that Match is a functor taking a string as the first argument and a regular expression as a second argument and returns true if the string matches the expression and false otherwise. Then one could write
Verify(MyString, Is.RelatedTo(MyRegExp).Using(Match));
Customizing value constraints¶
Constraints like LessThan, EqualTo and thier friends are based on the corresponding operators, <, ==, etc. If this is not appropriate for a type that is to be verified, e.g. if the operator is not defined for the type, it is possible to supply a custom functor to the constraint. This is done by the Using() method.
For example, suppose a complex number is modeled as
struct complex {
double Real;
double Imag;
};
and that we wish to verify that the absolute value of a complex number is less than some value. There is no constraint that does that “out of the box”. But if we define
class abs_value_less {
public:
bool operator(complex lhs, double, rhs) {
return ((lhs.Real*lhs.Real + lhs.Imag*lhs.Imag) < rhs*rhs);
}
} AbsValueLess;
Then we can say
Verify(MyComplex, LessThan(MyAbsValue).Using(AbsValueLess));
Of course we could have said
Verify((MyComplex.Real*MyComplex.Real + MyComplex.Imag*MyComplex.Imag) < MyAbsValue*MyAbsValue);
However, if the check fails the error message for the former will contain more information than for the latter case. The reason is that in the latter case the Verify() function only sees a boolean comparison and has no knowledge of the complex value.
The first construction, with a custom comparison operation, is also possible to use when verifying collections of values.
Hence, all value constraints have the Using() method and there is actually nothing special about the RelatedTo and Constrained constraints. They may in fact be used without the Using() call. Such a test will always fail however, since the default functor of these constraints returns false for any value.
Throws constraints¶
Throws constraints are used in order to check if a function, method or functor (class with overloaded call operator), throws a certain exception during invocation. The function or method must have the signature:
void my_function()
i.e. returntype void and no arguments. This is not as a severe limit as it may first seem. Any function may be wrapped up in such a function or method. Functors may have any return type, but must still be callable without arguments.
There are two forms of the exception constraint. The first takes the exception class to check for as a template argument. The second takes an instance of the exception class to look for as an argument:
// Template form
Throws.Exception<some_exception_class>()
// Argument form
Throws(SomeExceptionInstance)
The latter form uses call by reference and will copy the actual exception thrown during invocation into the given instance. That way it is possible to examine exceptions further e.g. to verify error messages etc. For example:
x_my_exception MyException;
Verify(my_function, Throws(MyException));
Verify(MyException.Message.find("my string") != string::npos);
The above will first check that my_function throws an instance of x_my_exception, then check that the string Message of that instance contains the string “my string”.
The general syntax is:
// Function
Verify(my_function, Throws.Exception<exception_class>());
Verify(my_function, Throws(ExceptionInstance));
// Method
Verify(MyInstance, my_method, Throws.Exception<exception_class>());
Verify(MyInstance, my_method, Throws(ExceptionInstance));
// Functor
Verify(MyFunctorInstance, Throws.Exception<exception_class>());
Verify(MyFunctorInstance, Throws(ExceptionInstance));
Verifying collections of values¶
It is possible to verify collections of values, e.g. arrays, vectors or lists against constraints. This is done by using Each in place of a single value. E.g. suppose that the array MyArray is to be verified against the array Expected, both of length 10. This would be done as follows:
// Check that corresponding elements are equal.
Verify(Each(MyArray, MyArray+10), Is.EqualTo(Each(Expected, Expected+10)));
// Suppose MyArray and Expected where vectors. Then the test would be
Verify(Each(MyArray.begin(), MyArray.end()), Is.EqualTo(Each(Expected.begin(), Expected.end())));
This will verify that each element in MyArray is equal to the corresponding element in Expected. This construction may be used together with all value constraints.
// Check that each element is less than corresponding element
Verify(Each(MyArray, MyArray+10), Is.LessThan(Each(Expected, Expected+10)));
Note that MyArray and Expected need not to be of the same type, it is enough that the constraint (e.g. EqualTo) is defined between the elements.
The Each construction may also be used to verify a collection against a single value.
// Check that all values are less than 3
Verify(Each(MyArray, MyArray+10), Is.LessThan(3));
// Verify that no element is NaN
Verify(Each(MyArray, MyArray+10), Is.Not.NaN);