Reference of Assertion Functions

Generic Assertions

bool testAssert(bool condition_);

bool testAssert(const AssertBean& bean_);

Assertions for general usage. The assertion passes when the condition is true. The AssertBean can be used by helper methods to report some meaningful message.

Expression Assertion

There is one special assertion

bool testAssertExpr(bool condition_);

It’s signature is exactly the same as the generic assertion testAssert. The difference is that OTest2 pre-processor parses expression passed as the parameter. If the root operator of the expression is one of the relational operators the assertion is handled exactly as the relational assertions are.

This is an implementation of the commont feature present in the Boost or Catch2. However, as it’s usual in the OTest2 framework, the feature is much cleaner. The pre-processor just parses the AST and there are no dirty tricks with templates and stealing of operands from the expression by prepending some text.

Relational Assertions

template<template<typename, typename> class Comparator_, typename A_, typename B_>
bool testAssertCmp(A_ a_, B_ b_);

This assertions checks two values (a_ and b_) by the specified comparator. The compararator must be a template which can be instantiated with the types A_ and B_. There are default comparators ::OTest2::Equal, ::OTest2::NotEqual, ::OTest2::Less, ::OTest2::LessOrEqual, ::OTest2::Greater and ::OTest2::GreaterOrEqual implemented in the otest2/comparison.h.

The default implementation compares values by the operators. There is one more specialization comparing the const char* by the std::strcmp function.

If the compared type doesn’t offer the comparison operator one can implement very own comparator. Or he can implement a specialization of the existing comparators.

If the assertion fails it prints values of the operands. Hence, the operand must be printable by the operator << to a C++ stream. If the compared type is not printable one can implement a specialization of the ::OTest::PrintTrait.

Note, that the chosen comparator is printed too. If you implement custom comparator you have to make its specialization of the ::OTest::PrintTrait template too.

template<typename A_, typename B_>
bool testAssertEqual(A_ a_, B_ b_);

template<typename A_, typename B_>
bool testAssertNotEqual(A_ a_, B_ b_);

template<typename A_, typename B_>
bool testAssertLess(A_ a_, B_ b_);

template<typename A_, typename B_>
bool testAssertLessOrEqual(A_ a_, B_ b_);

template<typename A_, typename B_>
bool testAssertGreater(A_ a_, B_ b_);

template<typename A_, typename B_>
bool testAssertGreaterOrEqual(A_ a_, B_ b_);

These assertions are just shortcuts using the default comparators.

Floating Point Assertions

template<template<typename, typename, typename> class Comparator_, typename A_, typename B_, typename P_ = long double>
bool testAssertCmpFP(A_ a_, B_ b_, P_ precision_ = DEFAULT_FLOAT_PRECISION);

This assertion allows to compare two floating point values with specified precision. There are two implemented comparators: ::OTest2::EqualFP and ::OTest2::NotEqualFP. User can implement own comparator or make a specialization of those two. As well as for generic comparators the print traits must be defined too.

And there are shortcut assertions too:

template<typename A_, typename B_, typename P_ = long double>
bool testAssertEqualFP(
    A_ a_,
    B_ b_,
    P_ precision_ = DEFAULT_FLOAT_PRECISION);

template<typename A_, typename B_, typename P_ = long double>
bool testAssertNotEqualFP(
    A_ a_,
    B_ b_,
    P_ precision_ = DEFAULT_FLOAT_PRECISION);

Item-Wise Assertions

template<template<typename, typename> class Comparator_, typename IterA_, typename IterB_>
bool testAssertItemWise(
    IterA_ begin_a_, IterA_ end_a_, IterB_ begin_b_, IterB_ end_b_);

template<template<typename, typename> class Comparator_, typename ContainerA_, typename IterB_>
bool testAssertItemWise(
    const ContainerA_& a_, IterB_ begin_b_, IterB_ end_b_);

template<template<typename, typename> class Comparator_, typename IterA_, typename ContainerB_>
bool testAssertItemWise(
    IterA_ begin_a_, IterA_ end_a_, const ContainerB_& b_);

template<template<typename, typename> class Comparator_, typename ContainerA_, typename ContainerB_>
bool testAssertItemWise(
    const ContainerA_& a_, const ContainerB_& b_);

The item-wise assertions apply the specified relational comparator on each pair of items with the same index in both lists a_ a b_. The assertion passes if all pairs pass. If the lists are different size the assertion fails.

The items of the lists must be printable by the operator << or they must have a specialization of the ::OTest::PrintTrait.

User can pass just 2 pairs of forward iterators. Or it can pass entire container instead of the iterator pair. The framework accesses the container’s iterators by the ::OTest2::ListContainerTrait. The default implementation works with the STL-style methods begin() and end(). One can implement custom specialization of the trait.

Lexicographical Assertions

template<template<typename, typename> class Compare_, typename IterA_, typename IterB_>
bool testAssertLexi(
    IterA_ begin_a_, IterA_ end_a_, IterB_ begin_b_, IterB_ end_b_);

template<template<typename, typename> class Compare_, typename ContainerA_, typename IterB_>
bool testAssertLexi(
    const ContainerA_& a_, IterB_ begin_b_, IterB_ end_b_);

template<template<typename, typename> class Compare_, typename IterA_, typename ContainerB_>
bool testAssertLexi(
    IterA_ begin_a_, IterA_ end_a_, const ContainerB_& b_);

template<template<typename, typename> class Compare_, typename ContainerA_, typename ContainerB_>
bool testAssertLexi(
    const ContainerA_& a_, const ContainerB_& b_);

The lexicographical assertions check two lists lexicographically. That means that the algorithm takes one item by one item from the both lists and compares them. If the items equal the algorithm moves forward to next item. If they don’t the assertion passes or fails according to used comparator. If one list is the prefix of the other one the comparator must resolve the relation.

There are prepared comparators ::OTest2::LexiLess, ::OTest2::LexiLessOrEqual, ::OTest2::LexiGreater and ::OTest2::LexiGreaterOrEqual implemented in the otest2/comparisonslexi.h. The default implementation is a composition of the ::OTest2::Less and ::OTest2::Greater comparators. If you have a specialization of these comparators you can use the lexicographical comparators even for your custom types.

A lexicographical comparator must implement two methods:

  • checkItems() which takes one item from the left list and one item form the right list and returns {-1, 0, 1} in the meaning {less, equal, greater}.
  • checkRests() taking one boolean for the left list and one for the right list. If the boolean is true the appropriate list has ended (there is no remaining tail of the list). The function returns true if the remaining tails fit the operator.

See the implementation in the otest2/comparisonslexi.h as an example.

The items of the lists must be printable by the operator << or they must have a specialization of the ::OTest::PrintTrait.

User can pass just 2 pairs of forward iterators. Or it can pass entire container instead of the iterator pair. The framework accesses the container’s iterators by the ::OTest2::ListContainerTrait. The default implementation works with the STL-style methods begin() and end(). One can implement custom specialization of the trait.

Map Assertions

template<template<typename, typename> class Compare_, typename ContainerA_, typename ContainerB_>
bool testAssertMap(const ContainerA_& a_, const ContainerB_& b_);

The assertion takes two associative containers and compares all items with the same key by the specified comparator. If a container is a multimap the items with the same key are compared in the order how they are iterated.

Note: the unordered_multimap container is not generally supported as the order of items with the same key is not defined. The container may be used only if it contains just unique keys.

The algorithm accesses the containers by the ::OTest2::MapContainerTrait. The user may write custom specialization to plug own container in. The default implementation works with the STL containers std::map, std::multimap, std::unordered_map and partially with the std::unordered_multimap.

The implementation of the trait must offer:

  • a typedef KeyType,
  • a typedef ValueType,
  • functions begin and end to access the container’s iterators,
  • a function equalRange returning range of items for specified key,
  • and a function keyEqual comparing keys for equality.

Both keys and value in the containers must be printable by the operator << or they must have implementation of the ::OTest::PrintTrait.

Long Text Assertions

This group of assertions computes diff (longest common sequence) of specified text files (difference is computed per text lines). If the texts are different, the assertion fails and the computed difference is printed. The text may be read from a C++ stream, from a string or from a text file.

bool testAssertLongTextSS(
    std::istream& a_, std::istream& b_);

bool testAssertLongTextST(
    std::istream& a_, const std::string& b_);

bool testAssertLongTextSF(
    std::istream& a_,const std::string& file_b_);

bool testAssertLongTextTS(
    const std::string& a_, std::istream& b_);

bool testAssertLongTextTT(
    const std::string& a_, const std::string& b_);

bool testAssertLongTextTF(
    const std::string& a_, const std::string& file_b_);

bool testAssertLongTextFS(
    const std::string& file_a_, std::istream& b_);

bool testAssertLongTextFT(
    const std::string& file_a_, const std::string& b_);

bool testAssertLongTextFF(
    const std::string& file_a_, const std::string& file_b_);

The last two characters of the assertion’s name code its parameters: S means stream, T means text string and F means file name.

Example of the output:

[.../test/longtexts.ot2:256] selftest::LongTextsComparisons::StreamStreamCompari
son: the texts are different
    ........................................
    0002 0002   : my awesome line 002
    0003 0003   : my awesome line 003
    0004 0004   : my awesome line 004
    0005      < : my awesome line 005
    0006      < : my awesome line 006
         0005 > : my awesome replaced line 005
    0007 0006   : my awesome line 007
    0008 0007   : my awesome line 008
    0009 0008   : my awesome line 009
    ........................................

Regression Assertions

template<typename Object_>
bool testRegression(const std::string& key_, const Object_& object_);

template<typename Object_>
bool testRegressionP(const std::string& key_, const Object_& object_);

template<typename Object_>
bool testRegressionW(const std::string& key_, const Object_& object_);

Regression assertions are used for checking and storing of regression test marks. The function with the P suffix prints current test mark to the standard output. The function with the W suffix stores current test mark into the regression storage.

The parameter key_ is an identifier of the stored mark. It must be unique in one test case. The stored marks are identified by a full key 'SuiteName'>>'CaseName'>>'key'. Be careful! If you rename the suite or the test case the stored marks won’t be found and the test will start failing.

The type of the object_ parameter must implement the method test_testMark or a specialization of the ::OTest2::RegressionTrait must exist for.

Usage of regression test marks is explained in the example.