Assertions¶
For the full code used here, see Source Code For Examples.
Basic Assertions¶
When your test is run, it is passed a Check object which is your interface to MosquitoNet within the test. Check overrides operator() to provide basic checking. We’ll concentrate on that for now. The test will continue even if any checks fail. The VAR macro indicates that we’re interested in the value and name of a particular variable. Each check will return true if the check passes, false otherwise.
This example will check the values of a and b.
static Suite s("examples", context("assertion",
given("some constants to assert with", [] (auto& check) {
int a = 0;
int b = 1;
check(VAR(a) == 0 && VAR(b) == 1);
})
));
When we run the test harness with –verbosity variables it will print out each check along with the value of the variables in that expression:
examples/assertion
Given: some constants to assert with
Then : ((a == 0) && (b == 1))
a = 0: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 16.
b = 1: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 16.
Assertions can also have a description:
check("a is one and b is two", VAR(a) == 0 && VAR(b) == 1);
Will output:
Then : a is one and b is two
((a == 0) && (b == 1))
a = 0: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 27.
b = 1: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 27.
For a less technical spec, we can suppress the expression (when a description is provided) and the variables with –verbosity checks:
examples/assertion
Given: some constants to assert with
Then : a is one and b is two
We can also provide context variables that are not checked, but provide context in the output:
check("`c` and `d` are provided for context", VAR(a) == 0 && VAR(b) == 1, VAR(c), VAR(d));
Outputs:
Then : `c` and `d` are provided for context
((a == 0) && (b == 1))
a = 0: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 33.
b = 1: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 33.
c = 2: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 33.
d = 4: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 33.
Also note that you can use an expression inside the VAR macro and all variables don’t have to be inside the VAR macro:
check("a is one and b is two", VAR(a) == 0 && b == 1 && VAR(a + c) == c);
Outputs:
Then : a is one and b is two
(((a == 0) && true) && (a + c == 2))
a = 0: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 37.
a + c = 2: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 37.
Exceptions¶
This will check std::exception or something derived from it is thrown:
check.throws("an exception is thrown", VAR(throwRuntimeError)());
This will check runtime_error or something derived from it is thrown:
check. template throws<runtime_error>("a runtime_error is thrown", VAR(throwRuntimeError)());
Again, we can provide context variables:
check.throws("`a` and `b` are provided for context", VAR(throwRuntimeError)(), VAR(a), VAR(b));
Explicit Failures¶
We can explicitly fail by throwing an exception. We can also use the Check object if we’d like to continue the test:
check.fail(VAR("explicit failure"));
And with context variables:
check.fail(VAR("`a` and `b` are provided for context"), VAR(a), VAR(b));
Containers¶
MosquitoNet provides some utility functions for working with containers. For example, you can check the length of a container:
vector<int> v{1,2,3};
check("the length of a vector is 3", length(VAR(v)) == 3u);
and it will output:
Then : the length of a vector is 3
(length(v) == 3)
v = [1, 2, 3]: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 96.
Other functions are:
- countEqual(container, value) gives the number of elements equal to value.
- countMatching(container, predicate) gives the number of elements matching predicate.
- allOf(container, predicate) is true iff all elements match predicate.
- anyOf(container, predicate) is true iff any elements match predicate.
- noneOf(container, predicate) is true iff no elements match predicate.
- length(container) gives the length of container.
- startsWith(container, prefixContainer) is true iff container starts with prefixContainer.
- endWith(container, postfixContainer) is true iff container ends with postfixContainer.
- contains(container, subSequenceContainer) is true iff subSequenceContainer is a sub-sequence of container.
Customizing Assertions¶
You can customize assertions to use your own functions. If you have a non-overloaded function and you don’t need template argument deduction, you can just use the function as-is in assertions. For example, given:
int multiply(int x, int y) { return x * y; }
multiply can be used directly in assertions:
check("3 squared is 9", VAR(multiply) (3, 3) == 9);
Arguments can be recorded as variables if required:
int three = 3;
check("3 squared is 9", VAR(multiply) (VAR(three), 3) == 9);
If you have an overloaded function or require template argument deduction, or just want a cleaner syntax, you can provide a wrapper for your function. For example, given:
template<typename Value>
Value multiplyOverloaded(Value x, Value y) {
return x * y;
}
template<typename Value>
Value multiplyOverloaded(Value x, Value y, Value z) {
return x * y * z;
}
You can provide the wrapper:
template<typename... Args>
auto multiplyOverloadedProxy(Args&&... args) {
return makeFunction(
"multiplyOverloaded",
[] (auto&&... args) { return multiplyOverloaded(forward<decltype(args)>(args)...); }
)(forward<Args>(args)...);
}
then the check:
check("3 cubed is 27", multiplyOverloadedProxy(VAR(three), 3, 3) == 27);
will output:
Then : 3 cubed is 27
(multiplyOverloaded(three, 3, 3) == 27)
three = 3: file "/work/build/MosquitoNet/cpp/test/src/Examples/AllExamples.cpp", line 104.