Wiki
xUnit++ / TestEvents
Assert and Check
xUnit++ has a robust suite of test assert methods. While most C++ testing frameworks use preprocessor macros to implement only a few checks, xUnit++ provides two class instances with many built-in methods. And since these tests are not implemented with macros, you get much nicer feedback while editing (assuming your editor can provide such detail) and compiling.
There are three ways to assert test events: Assert
, Check
, and Warn
. With one exception, they offer the same check methods. Assert
will halt the test immediately if any check fails, Check
will log the failure but continue, and Warn
will not cause the test to fail by itself, but the "error" will be logged.
Warn.Fail(); // warning message logged, test is not a failure (yet)
Check.Fail(); // failure is logged, test is marked as failing, test execution continues
Assert.Fail(); // stops the test here
Check.Fail(); // test never executes this line
The Methods
As stated before, the test objects share the same check methods, with one exception: Assert
offers Throws
while Check
and Warn
do not.
Contains
asserts that a container contains some value. Overloads exist for raw strings andstd::string
.ContainsPred
is an alternative form ofContains
which takes a predicate instead of a value.DoesNotContain
asserts that a container does not contain some value. Overloads exist for raw strings andstd::string
.DoesNotContainPred
is an alternative form ofDoesNotContain
which takes a predicate instead of a value.DoesNotThrow
asserts that the given code does not throw any exceptions. Anything that resolves to the equivalent ofvoid (*)()
will work.Equal
tests object values for equality. There are overloads for raw strings,std::string
, floating point types (with precision, instead of tolerance), and iterator ranges.Empty
will assert that the container object is empty.TContainer::empty()
will be used if it exists, otherwise the container will be converted to a range usingstd::begin
andstd::end
.Fail
will automatically fail the test.False
will fail the test if the supplied parameter resolves totrue
.InRange
checks that the given value fits within the range [min
,max
).NotEmpty
is the opposite ofEmpty
.NotEqual
is the opposite ofEqual
.NotInRange
checks that the given value does not fit within the range [min
,max
).NotNull
checks that the value is not equal tonullptr
.NotSame
verifies that the supplied objects are not the same object instance.Null
checks that the value is equal tonullptr
.Same
checks that the supplied objects are the same object instance.Throws
is anAssert
-only member that checks that the supplied code throws a specific exception. If it succeeds, it will return the exception to your test.
auto ex = Assert.Throws<std::exception>([]() { throw std::runtime_error(""); });
Printing Values
Some methods may try to print the values of the objects using to_string
with argument-dependent lookup (Koenig lookup). To take advantage of this, implement a to_string
function within your object's namespace.
namespace NS
{
class A {};
std::string to_string(const A &a) { return "A"; }
}
If a corresponding to_string
can't be found, xUnit++ falls back to printing the object's type with typeid(obj).name()
.
Custom Messages
If you want to add a custom message to failing tests, use the overloaded operator <<
.
Assert.Fail() << "This is an example message " << some_value;
File and Line Info
Normally, when a test fails the test runner will report the file and line number for the test itself. This is typically sufficient for most tests, as tests should really only assert one thing at a time. However, if you want to be specific about which check failed, each check method accepts an optional xUnitpp::LineInfo
object. The easiest way to do this is to pass the LI
macro as the final parameter to the test.
Assert.Equal(0, 1, LI) << "0 is never equal to 1!";
Extra Logging
If you need more logging output within the tests, use the Log
object. Three levels of logging are implemented: Debug, Information, and Warning:
Log.Debug << "This is a debug-level message: " << some_value;
Log.Info << "This is an info-level message: " << some_value;
Log.Warn << "This is a warning-level message, and will automatically mark the running test has having a warning status. " << some_value;
The log levels will normally print the file and line of the test (like the check methods), but they also accept the LI
macro:
Log.Info(LI) << "This message will include the exact line number.";
Updated