对不同输入的不同 catch2 检查

Different catch2 checks on different inputs

我正在尝试测试一些需要进行一些设置才能使用的代码,我想避免重复设置步骤。设置步骤对输入有一定的依赖性,但结果可能会因输入的具体内容而大不相同。有什么好的方法可以为此设置一个 catch2 测试用例吗?

举例来说,让我们考虑一个我们可能想要测试的非常基本的对象:

#include <cmath>
struct SquareRoot {
  double n;
  double root() { return std::sqrt(n); }
};

如果我们想为此编写一些测试,“阳性”和“阴性”显然是要检查的(“零”是三分之一)。对于这两种情况,我们都需要创建一个依赖于输入的对象,然后调用函数,但实际的检查是非常不同的。

#include <catch2/catch.hpp>
TEST_CASE("SquareRoot") {
  SECTION("positive") {
    double n = 4.0;
    SquareRoot sqrt{n};          // <---
    double result = sqrt.root(); // <---
    REQUIRE(result == 2.0);
  }

  SECTION("negative") {
    double n = -4.0;
    SquareRoot sqrt{n};          // <---
    double result = sqrt.root(); // <---
    REQUIRE(std::isnan(result));
  }
}

我可以想象 GENERATE() 输入,但是你需要一些方法来决定之后 运行 实际检查什么。

TEST_CASE("SquareRoot") {
  double n = GENERATE(4.0, -4.0);
  SquareRoot sqrt{n};
  double result = sqrt.root();
  // Which REQUIRE do I run here???
}

在真实系统中对象系统更为复杂。如果设置超过几行,我已经成功地将它分解为一个单独的函数,但需要在每次测试中重复。同样,通常对结果进行不止一次检查(例如,我们可能会在此处检查 errno 是否定的情况)。

即使对于简单的情况,我也倾向于编写小的辅助函数(或 lambda)。对于您的示例,这可能很短:

#include <catch2/catch.hpp>

auto rootTest(double x)
{
    return SquareRoot{x}.root();
}

TEST_CASE("SquareRoot") {
  SECTION("positive") {
    CHECK(rootTest(4.0) == 2.0);
    REQUIRE(errno == 0);
  }

  SECTION("negative") {
    CHECK(std::isnan(rootTest(-4.0)));
    REQUIRE(errno);
  }
}

在更复杂的情况下,您可以另外定义一个 POD 结构,让您的测试函数 return 多个命名值,这有助于使测试条件易于阅读。您还可以在函数内部使用 Catch2 语句,以防您有无论输入如何都适用的测试。