I have a set of inputs and their corresponding expected outputs for a function.
The test is currently written as follows:
TEST_CASE("test reverse_and_double")
{
    struct { string input, string expected_output } tests[] = {
        { "abcd", "dcba" },
        { "hello", "olleh" },
        //...
    };
    for(auto &t : tests) {
        string output = my_reverse(t.input);  // function under test
        REQUIRE(output.size() == t.expected_output.size())
        CHECK(std::equal(output.begin(), output.end(), t.expected_output.begin()));
        //... many lines of CHECK & REQUIRE here...
    }
}
Now, in theory, unit-tests should not have (complex) mechanisms in order to be readable.
GENERATE() is the way Catch offers in order to use the same CHECKs for different inputs.
So, I tried it  and I removed the forloop:
TEST_CASE("test reverse_and_double")
{
    struct { string input, string expected_output } t = GENERATE(
        { "abcd", "dcba" },
        { "hello", "olleh" },
        //...
    );
    string output = my_reverse(t.input);  // function under test
    REQUIRE(output.size() == t.expected_output.size())
    CHECK(std::equal(output.begin(), output.end(), t.expected_output.begin()));
    //... many lines of CHECK & REQUIRE here...
    }
}
However, there still is a 'mechanism' buried in the struct of inputs vs expected outputs. Many people will have different ways of writing this.
I suppose this is a common pattern in unit-tests.
Does Catch offer a build-in construct to express such situations in a consistent way?
Yes it is possible, but documentation lacks off good examples, in this case you need feed table<...> generator to GENERATE macro:
std::string my_reverse(std::string_view s)
{
    return {s.rbegin(), s.rend()};
}
TEST_CASE("test reverse_and_double")
{
    auto [input, expected_output] = GENERATE(table<std::string, std::string>({
        { "abcd", "dcba" },
        { "hello", "olleh" },
    }));
    CAPTURE(input);
    REQUIRE(my_reverse(input) == expected_output);
}
https://godbolt.org/z/GbrPxdbrb
I had problems understanding documentation and had to inspect unit test and other projects source code on github to fill gaps.
Note I used CAPTURE so it is clear which argument was used when test fails.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With