首页 > 解决方案 > 谷歌测试框架不打印 std::optional

问题描述

我有一个数据结构,它被通知给监听器。在它的众多变量中,它有一个可选的 double 表示一个角度:

struct Data
{
    // ...other data fields
    std::optional<double> angle;
    // ...other data fields
};

我想检查是否使用 right 调用了侦听器angle。我正在使用Google Test Framework,所以我在这里定义了自己的匹配器:

MATCHER_P( HasAngle, angle, "" )
{
    if ( !arg.angle.has_value( ) )
    {
        return false;
    }

    return arg.angle.value( ) == angle;
}

并检查是否使用预期值调用了我的侦听器。

EXPECT_CALL( listener, on_event( HasAngle( 45.0 ) ) ).Times( AtLeast( 1 ) );

最终没有使用预期值调用侦听器,但打印输出确实不可读:

  Expected arg #0: has angle 45
       Actual: 128-byte object <75-85 4D-52 FB-21 F9-BF 47-D9 48-53 FB-21 09-C0 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 01-17 23-83 FD-7F 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00 00-00>

实际值是无法理解的。我没想到框架默认不支持 C++17 类型,所以我开始阅读Google Test Framework Cookbook并尝试添加自己的PrintTo重载,如下所示:

void
PrintTo( const std::optional< double >& opt, std::ostream* os )
{
    if ( !opt )
    {
        *os << "std::nullopt";
    }
    else
    {
        *os << *opt;
    }
}

不用说,它没有帮助。我非常确定的是,由于输出表明128-byte object它正在尝试打印唯一std::optional<double>而不是整个struct Data,这比这要大得多,但是尽管重载了它并没有成功PrintTo

标签: c++c++17googletestgooglemock

解决方案


std::optional如果您使用匹配器,GoogleTest 会打印值Optional(m)

示例测试:

TEST_F(MyClassTests, myFunctionTest)
{
    std::optional<std::string> actual_value = "foo";
    std::string expected_value = "bar";

    EXPECT_THAT(actual_value, testing::Optional(expected_value));
}

输出将是相似的,但在加密 128-byte object <75-85 4D-52 FB-21 F9-BF...文本之后,将额外打印包含的值:

...
[ RUN      ] MyClassTests.myFunctionTest
myclasstests.cpp:123: Failure
Value of: actual_value
Expected: value is equal to "bar"
  Actual: 40-byte object <DE-AD BE-EF CA-FE BA-BE ...>, whose value "foo" doesn't match
[  FAILED  ] MyClassTests.myFunctionTest (0 ms)
...

如果您希望 astd::optionalstd::nullopt测试用例中,您很可能会这样做:

EXPECT_EQ(actual_value, std::nullopt);

actual_value如果实际有值,测试将失败。但同样,实际值不会被打印出来。作为一种解决方法,您可以像这样实现测试:

if (actual_value) {
    FAIL() << "actual_value is not std::nullopt, but: " << actual_value.value();
}

推荐阅读