强制googletest签名与无符号比较失败

时间:2016-01-04 19:37:59

标签: c++ googletest

首先,我是googletest框架的新手,所以要善待。

我有一个功能

void setID(const int id)
{
    ID = id;
}

其中ID是全局unsigned int。 (是的,全局变量很糟糕,我只想弄清楚我在做什么。)

我的单元测试看起来像这样

TEST_F(TempTests, SetId)
{
    // Arrange
    int id = -99;

    // Act
    setId(id);

    // Assert
    EXPECT_EQ(id, ID);
}

问题是我的单元测试总是通过,我需要它失败,因为ID应该是signed int而不是unsigned int。如果我没有在视觉上发现错误,单元测试就会通过,并且可能会在以后导致错误。

为了确保将来不会发生这种情况,最好在这种情况下单位测试比较失败。

我已尝试以各种方式静态转换idID到已签名和未签名的整数。 我尝试用EXPECT_TRUE(id == ID)静态将变量以各种方式转换为有符号和无符号的int。 但在所有这些情况下,结果都是通过测试。

那么如何让gtest比较id的签名值和ID的无符号值,以便测试失败,因为id将是-99和{{1}将是4294967197?

2 个答案:

答案 0 :(得分:2)

编译器需要将类型转换为相等。我建议阅读this related answer

您可以创建自定义googletest比较器。即使没有,你至少可以使用类似的东西:

#include <iostream>
#include <cstdint>
#include <limits>
#include <type_traits>
#include <typeinfo>

template <class T>
class SignedUnsignedIntCompare final /* final for non-virtual dtor, remember to make dtor virtual if you need to inherit */ {
public:
    const T & v;
    SignedUnsignedIntCompare(const T & v) : v(v) {}
    SignedUnsignedIntCompare(SignedUnsignedIntCompare && move_ctor) = default;
    SignedUnsignedIntCompare(const SignedUnsignedIntCompare & copy_ctor) = default;
    SignedUnsignedIntCompare & operator=(SignedUnsignedIntCompare && move_assign) = default;
    SignedUnsignedIntCompare & operator=(const SignedUnsignedIntCompare & copy_assign) = default;
    ~SignedUnsignedIntCompare() = default;

    template <class TT>
    bool operator==(const TT & i) const {
        if ( std::numeric_limits<T>::is_signed != std::numeric_limits<TT>::is_signed ) {
            return ((v == i) && (T(v) <= std::numeric_limits<TT>::max()) && (TT(i) <= std::numeric_limits<T>::max()));
        }
        return (v == i);
    }
};

typedef SignedUnsignedIntCompare<int> SignedIntCompare;
typedef SignedUnsignedIntCompare<unsigned> UnsignedIntCompare;

int main() {
    int i = -99;
    unsigned int u = i;

    std::cout << (i == u) << " vs " << (SignedIntCompare(i) == u) << std::endl;

    return 0;
}

此时,您可以使用EXPECT_TRUE或类似的布尔检查,例如:

TEST(foo, bar) {
    int id = -99;
    setId(id);
    EXPECT_TRUE(SignedUnsignedIntCompare<decltype(ID)>(ID) == id);
}

答案 1 :(得分:1)

所以我不确定如何给予信任,但我最终结合使用了inetknght和mkk的建议。

TEST_F(TempTests, SetId)
{
    // Arrange
    int id = -99;

    // Act
    setId(id);

   // Assert
   EXPECT_TRUE(std::numeric_limits<decltype(id)>::is_signed == std::numeric_limits<decltype(ID)>::is_signed);
   EXPECT_EQ(id, ID);
}

根据inetknght的建议,通过检查已签名的类型,我可以通过测试失败,因为类型都没有签名。根据mkk的建议,使用decltype我可以获得声明的变量类型,而不会在更正ID类型时修改单元测试。当ID类型得到纠正后,测试就会通过。

修改

根据Adrian McCarthy的建议,我还添加了-Werror =转换为我的编译器标志。