如何测试函数调用顺序

时间:2008-09-17 00:45:23

标签: c++ unit-testing tdd

考虑这样的代码:

class ToBeTested {
public:
  void doForEach() {
    for (vector<Contained>::iterator it = m_contained.begin(); it != m_contained.end(); it++) {
       doOnce(*it);
       doTwice(*it);
       doTwice(*it);
    }
  }
  void doOnce(Contained & c) {
    // do something
  }
  void doTwice(Contained & c) {
    // do something
  }

  // other methods
private:
  vector<Contained> m_contained;
}

我想测试一下,如果我用3个值填充向量,我的函数将按正确的顺序和数量调用。例如,我的测试看起来像这样:

tobeTested.AddContained(one);
tobeTested.AddContained(two);
tobeTested.AddContained(three);

BEGIN_PROC_TEST()
SHOULD_BE_CALLED(doOnce, 1)
SHOULD_BE_CALLED(doTwice, 2)
SHOULD_BE_CALLED(doOnce, 1)
SHOULD_BE_CALLED(doTwice, 2)
SHOULD_BE_CALLED(doOnce, 1)
SHOULD_BE_CALLED(doTwice, 2)

tobeTested.doForEach()
END_PROC_TEST()

您如何建议测试?有没有办法用CppUnit或GoogleTest框架做到这一点?也许其他一些单元测试框架允许执行此类测试?

据我所知,如果不从这些函数调用任何调试函数,这可能是不可能的,但至少可以在某些测试框架中自动完成。我不喜欢扫描跟踪日志并检查它们的正确性。

UPD :我不仅要检查对象的状态,还要检查执行顺序以避免性能问题尽可能早的阶段(总的来说,我想知道我的代码完全按照我的预期执行)。

7 个答案:

答案 0 :(得分:1)

您可以查看mockpp

答案 1 :(得分:1)

您应该能够使用任何好的模拟框架来验证对协作对象的调用是否按特定顺序完成。

但是,你通常不会测试一个方法是否在同一个类上调用其他方法...为什么会这样?

通常,当您测试课程时,您只关心测试其公开可见的状态。如果你测试 其他任何事情,你的测试都会阻止你以后重构。

我可以提供更多帮助,但我不认为你的例子是一致的(AddContained方法的实现在哪里?)。

答案 2 :(得分:1)

不是试图弄清楚调用了多少函数,而是按照什么顺序查找一组输入,如果按正确的顺序调用,则只能产生预期的输出。

答案 3 :(得分:1)

如果您对性能感兴趣,我建议您编写一个测量性能的测试。

检查当前时间,运行您关注的方法,然后再次检查时间。断言所花费的总时间少于某个值。

检查方法按特定顺序调用的问题是您的代码必须更改,并且您不希望在发生这种情况时更新测试。您应该专注于测试实际需求,而不是测试满足该要求的实现细节。

那就是说,如果你真的想测试你的方法是按照特定的顺序调用的,你需要做以下事情:

  1. 将它们移至另一个班级,称之为Collaborator
  2. 将此其他类的实例添加到ToBeTested类
  3. 使用模拟框架将ToBeTested上的实例变量设置为Collborator类的模拟
  4. 调用测试中的方法
  5. 使用您的模拟框架断言以正确的顺序在模拟上调用方法。
  6. 我不是本地cpp发言人所以我不能评论你应该使用哪种模拟框架,但我看到其他一些评论者在这方面添加了他们的建议。

答案 4 :(得分:0)

一些模拟框架允许您设置有序期望,这可以让您确切地说出您按特定顺序调用的函数。例如,C#的RhinoMocks允许这样做。

我不是C ++编码器,所以我不知道C ++可用的是什么,但这是一种可能允许你尝试做的工具。

答案 5 :(得分:0)

http://msdn.microsoft.com/en-au/magazine/cc301356.aspx

这是一篇关于上下文绑定对象的好文章。它包含一些非常高级的东西,但是如果你不是懒惰而且真的想要了解这类东西,它将会非常有用。

最后你可以写下这样的东西: [CallTracingAttribute()] 公共类TraceMe:ContextBoundObject {...}

答案 6 :(得分:0)

您可以使用ACE(或类似的)调试框架,并在测试中配置调试对象以流式传输到文件。然后你只需要检查文件。