2

我的 Catch Testframework 中有以下简单的表达式。理想情况下,如果测试失败,测试应该发出警告。

不幸的是,Catch 无法编译以下代码片段:

#define CATCH_CONFIG_MAIN
#include "catch2.hpp"

TEST_CASE("Simple") {
    int a = 4;
    int b = 1;
    CHECK(a == 5 || b == 2);
}

Visual Studio 2015 发出以下错误:

error C2676: Binary operator "||": "const Catch::BinaryExpr<LhsT,const int &>" does not define this operator or a conversion for this operator of to suitable type

我会期待类似以下的内容:

4==5 || 1==2 => false || false => false

这是否可能与 Catch 或我必须使用额外的括号:

#define CATCH_CONFIG_MAIN
#include "catch2.hpp"

TEST_CASE("Simple") {
    int a = 4;
    int b = 1;
    CHECK((a == 5 || b == 2));
}
4

2 回答 2

4

如果您阅读文档,您会发现一个部分说:

检查(a == 2 || b == 1);这个表达式太复杂了,因为 || 操作员。如果要检查几个属性之一是否成立,可以将表达式放入括号中(与 && 不同,表达式分解为多个 CHECK 是不可能的)。

另请注意...

我会期待类似以下的内容:

4==5 || 1==2 => false || false => false

...您的期望略有偏差。||是短路的,这意味着如果第一个操作数的计算结果为false,则不计算第二个操作数。

于 2018-05-03T08:42:06.193 回答
2

Catch Classic 曾经提供更好的错误,因为它会在实例化名为 something 的类型时出错 CATCH_STATIC_ASSERT_EXPRESSION_TOO_COMPLEX_REWRITE_...,但显然在重写表达式捕获层期间这种情况消失了。

无论如何,user463035818已经提供了简单的答案,将表达式括在括号中。我想详细说明为什么不支持包含运算符&&的表达式。||

&&不支持为什么和操作符分为三个部分||,其中两个是实用的,一个是哲学的。

1) 用于分解表达式并漂亮打印它的 TMP 魔法无法正确模拟内置运算符的短路行为。这意味着此类表达式的行为将与用户的期望不同。

2) 已经提到的 TMP 魔法在编译时间方面相当昂贵,即使我们有专门的一元和二元表达式路径。拥有可变参数表达式的通用路径最终可能会非常昂贵。

3)||在断言中的使用通常是代码(测试)气味。在一个合理的单元测试中,您应该能够准确地表达预期结果,并且对于不正确的情况(例如迭代无序集),合乎逻辑或仍然不是一个好的工具解决方案。

注意 1:&&在单元测试中使用 (logical and) 是完全合理的,实际上重写表达式使用&& 来编译并且仍然短路是相当简单的:

REQUIRE((expr1 && expr2 && expr3));

REQUIRE(expr1);
REQUIRE(expr2);
REQUIRE(expr3);

注意 2:这开始是对另一个答案的评论,但后来超出了允许的长度,我注意到 Catch2 的错误消息确实很糟糕,所以我打开了一个问题

于 2018-05-04T08:48:07.373 回答