Google 测试框架不打印 std::optional

nya*_*108 6 c++ googletest googlemock c++17

我有一个正在通知侦听器的数据结构。在它的许多变量中,它有一个可选的 double 代表一个角度:

struct Data
{
    // ...other data fields
    std::optional<double> angle;
    // ...other data fields
};
Run Code Online (Sandbox Code Playgroud)

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

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

    return arg.angle.value( ) == angle;
}
Run Code Online (Sandbox Code Playgroud)

并检查我的侦听器是否正在使用预期值进行调用。

EXPECT_CALL( listener, on_event( HasAngle( 45.0 ) ) ).Times( AtLeast( 1 ) );
Run Code Online (Sandbox Code Playgroud)

最终,监听器没有被调用并具有预期的值,但打印输出确实不可读:

  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>
Run Code Online (Sandbox Code Playgroud)

实际价值难以理解。我没想到该框架默认不支持 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

sta*_*tor 5

如果您使用匹配器, GoogleTest 会打印std::optionalOptional(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));
}
Run Code Online (Sandbox Code Playgroud)

输出将类似,但在神秘 128-byte object <75-85 4D-52 FB-21 F9-BF...文本之后,将另外打印包含的值:

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

    EXPECT_THAT(actual_value, testing::Optional(expected_value));
}
Run Code Online (Sandbox Code Playgroud)

如果您希望 astd::optional出现std::nullopt在测试用例中,您很可能会这样做:

EXPECT_EQ(actual_value, std::nullopt);
Run Code Online (Sandbox Code Playgroud)

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

if (actual_value) {
    FAIL() << "actual_value is not std::nullopt, but: " << actual_value.value();
}
Run Code Online (Sandbox Code Playgroud)


Łuk*_*zyk 1

在测试中为您的类型定义标准输出运算符应该会有所帮助并在 gmock 错误消息中使用

template <class T>
std::ostream & operator<<(std::ostream & os, std::optional<T> const & opt)
{
  if (opt) return os << opt.value();
  return os << "EMPTY";
}
Run Code Online (Sandbox Code Playgroud)