Catch2中是否有一种构造来表示输入与预期值的映射?

huangapple go评论81阅读模式
英文:

is there a construct in catch2 to express a mapping of inputs vs. expected values?

问题

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 for loop:

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 built-in construct to express such situations in a consistent way?

英文:

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?

答案1

得分: 1

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.

英文:

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.

huangapple
  • 本文由 发表于 2023年4月10日 22:33:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/75978008.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定