测试相等运算符

时间:2018-04-12 04:12:06

标签: c++ tdd googletest

当我编写单元测试时,我通常会试图预防我(或许是其他开发人员)可能出现的错误。

以此类Foo为例,它具有相等运算符:

struct Foo {
  int m_foo;

  bool operator==(const Foo& other) const {
    return m_foo == other.m_foo;
  }
};

// test code
TEST(FooEquality, Equal) {
  Foo f1, f2;
  f1.m_foo = 1;
  f2.m_foo = 1;

  EXPECT_EQ(f1, f2);
}

TEST(FooEquality, NotEqual) {
  Foo f1, f2;
  f1.m_foo = 1
  f2.m_foo = 2;

  EXPECT_NE(f1, f2);
}

一个简单但很可能的问题:将来我添加一个新的成员变量m_bar并忘记更新相等运算符。

struct Foo {
  int m_foo;
  int m_bar;

  bool operator==(const Foo& other) const {
    // BUG: We didn't check m_bar, but tests still pass!
    return m_foo == other.m_foo;
  }
};

是否有一种干净的方法为此编写测试?

1 个答案:

答案 0 :(得分:1)

  

是否有一种干净的方法为此编写测试?

不是通常意义上的,没有。

也就是说,TDD中讨论的单元测试是合同规范的表达;它们不会限制实施,只会限制可观察的结果。

这意味着如果您在实现中进行了与先前API向后兼容的更改,那么单元测试将会观察到等效行为。

单元测试不应该检查实现的内部。

如果您查看Beck的按示例进行的测试驱动开发,您会发现它有一个正在运行的待办事项列表,用于跟踪他预期需要的测试。当他对特定模式的识别帮助他确定一个新的测试添加到套件中时,他添加到此列表中。

但实际的触发因素是他作为开发人员的经历。所以赋值算子的新测试应该来自你的认识,“哦,我已经改变了状态的内部表示,我是否需要添加任何新的测试?”就像编写一个大的五个一样。

也就是说,可能能够通过静态分析获得您想要的结果。这个想法的粗略草图是分析工具可以查看类成员和赋值运算符,而不是缺少明确原因的缺失成员。

这里有一个closed question堆栈溢出,可以让你开始使用一些选项。

免责声明:自从我使用C ++沙箱已经有好几年了,我不知道今天的分析工具涵盖了什么。我只是建议作为一个可能的起点。