Recently, I have experimented with Catch, and it's really great. It offers a lot of flexibility and is very smart at interpreting the code. The only unfortunate thing is that its header-only nature is really nice to get things up and running quickly, but leads to unnecessarily long compile times in long-term projects.
Anyway, I would be willing to contribute with some test cases.
I personally think the BDD-style testing is too verbose if applied rigorously.
SCENARIO("Constructing sf::Vector2")
{
WHEN("default constructor is used")
{
sf::Vector2i vector;
THEN("x and y are 0")
{
CHECK(vector.x == 0);
CHECK(vector.y == 0);
}
}
}
vs.
SECTION("Default-constructing sf::Vector2 yields (0, 0)")
{
sf::Vector2i vector;
CHECK(vector.x == 0);
CHECK(vector.y == 0);
}
It is absolutely obvious that we expect members to be zero after default construction, and one annotation in the
SECTION macro is more than enough to describe it. In many cases, the
CHECK expressions alone would suffice. Writing it three times in text over 13 lines feels to me like
++i; // increment i
that is, unnecessary noise, which makes code harder to read and more difficult to maintain. The simple
sf::Vector2i test takes already 220 lines. Imagine how this explodes for other classes that have 15 no-brainer setters/getters, when you have to repeat the same verbosity again and again.
What I really love about Catch is that code written with it can be tremendously concise -- unlike awful test frameworks where you have to write class hierarchies and spend an insane amount of time for nothing. I suggest we exploit this advantage where possible, and I'm sure I'm much more motivated to write test cases if I'm not dealing with so much boilerplate. I would end up copy-pasting anyway, and that's never a good sign
There may be more complex cases where we really need to state what was meant. BDD style is one option, but keep in mind the
WHEN/THEN macros are semantically equivalent to
SECTIONs, so we can achieve the same either way.
Edit: Even more extreme example:
WHEN("equal vectors are tested for equality")
{
bool equal = (firstEqualVector == secondEqualVector);
THEN("the result is true")
{
CHECK(equal == true);
}
}
vs.
SECTION("operator==") // do we really need to explain == semantics?
{
CHECK(firstEqualVector == secondEqualVector);
}
Both the
SECTION caption and the expression given to
CHECK are visible in the output if the test fails, so that's already 2 times obvious
And apart from that, the second code is better because it contains the objects to check in the
CHECK macro, allowing Catch to evaluate the operand's values. One would need to define a string output for
sf::Vector2, but then one would immediately see
where the implementation is broken aka
"(3,3) == (3,3)", rather than just an unhelpful
"false == true".