用于验证等式运算符的C ++测试随着时间的推移与struct保持一致

时间:2011-05-02 00:10:50

标签: c++ testing

我投了@TomalakGeretkal对合同的好评;我还没有接受答案,因为我的问题是如何以编程方式检查equals函数。


我有一个POD结构&平等运算符,系统的(非常)小部分,具有> 100名工程师。

随着时间的推移,我希望修改结构(成员添加/删除/重新排序),我想编写一个测试来验证相等操作是否正在测试结构的每个成员(例如,作为结构保持最新变化)。

正如Tomalak指出的那样 - 评论& “按合同”通常是执行此操作的最佳/唯一方式;但是在我的情况下,我期待问题,并希望探索是否有任何方法可以主动捕获(至少很多)修改。

我没有得到满意的答案 - 这是我想到的最好的答案:

-new up two instances struct (x, y), fill each with identical non-zero data.
-check x==y
-modify x "byte by byte"
    -take ptr to be (unsigned char*)&x
    -iterator over ptr (for sizeof(x))
        -increment the current byte
        -check !(x==y)
        -decrement the current byte
        -check x==y

如果相等运算符捕获了每个字节,则测试通过(注意:对此有一个警告 - 并非所有字节都用在x的编译器表示中,因此测试必须'跳过'这些字节 - 例如硬编码忽略字节)

我提出的测试存在重大问题:(至少)“不关心”字节,以及增加x中类型的一个字节的事实可能不会导致该存储器位置处的变量的有效值。

有更好的解决方案吗?

(这应该没关系,但我使用VS2008,rtti关闭,googletest套件)

5 个答案:

答案 0 :(得分:6)

虽然很容易通过这样的自我检查来使代码“傻瓜式”,但我的经验是,保持自我检查本身是万无一失的,这是一个傻瓜的差事。

保持简单并本地化任何更改的效果。在结构定义中写一条注释,清楚表明如果结构是,则必须更新相等运算符;那么,如果失败了,那只是程序员的错。

知道这对您来说似乎不是最佳选择,因为它可能会在未来留下用户错误的可能性,但实际上您无法解决这个问题(至少没有让您的代码骇人听闻)复杂的,并且通常最实际的是不要打扰。

答案 1 :(得分:2)

我同意(并赞成)Tomalak的回答。你不太可能找到一个万无一失的解决方案。尽管如此,一种简单的半自动化方法可能是验证相等运算符中的预期大小:

MyStruct::operator==(const MyStruct &rhs) 
{
  assert(sizeof(MyStruct) == 42);  // reminder to update as new members added

  // actual functionality here ...
}

这样,如果添加了任何新成员,则断言将触发,直到有人更新了相等运算符。当然,这不是万无一失的。 (成员变量可能被替换为相同大小的东西等)尽管如此,它是一个相对简单的(一行断言),可以很好地检测错误情况。

答案 2 :(得分:0)

我确信我会为此而投票但是......

模板相等函数如何引用int参数以及正在测试的两个对象。等于函数将返回bool,但会将sizeof(T)增加size参数(int)。

然后有一个大的测试函数,为每个对象调用模板并总计总大小 - >将此总和与对象的大小进行比较。虚函数/继承等的存在可能会破坏这个想法。

答案 3 :(得分:0)

在自我测试中正确解决这个问题实际上是一个难题。

我能想到的最简单的解决方案是采用一些模板功能,这些功能可以在多种类型上运行,执行必要的转换,升级和比较,然后在外部单元测试中验证结果。当引入突破性变化时,至少你会知道。

使用组合等方法更容易维护/验证其中一些挑战,而不是扩展/子类化。

答案 4 :(得分:0)

同意Tomalak和Eric。我用它来解决类似的问题。

除非定义了DEBUG,否则Assert不起作用,因此您可能会发布错误的代码。这些测试并不总能可靠地运行。如果结构包含位字段,或者插入的项占用了编译器与字边界对齐而导致的松弛空间,则大小不会改变。因此,它们提供的价值有限。 e.g。

struct MyStruct {   
    char a ;
    ulong l ;
}

更改为

struct MyStruct {   
    char a ;
    char b ;  
    ulong l ;
}

两个结构都是8个字节(在32位Linux x86上)