Google C++测试框架系列入门篇

发表于:2014-04-10来源:博客园作者:移山测试工作室黑灯老点击数: 标签:C++测试框架
Google C++测试框架系列入门篇 GTest帮助你写更好的C++测试代码。 不管你在什么平台上工作,无论是Linux,Windows还是Mac,只要你使用C++,GTest就可以帮助你。

  GTest帮助你写更好的C++测试代码。

  不管你在什么平台上工作,无论是LinuxWindows还是Mac,只要你使用C++,GTest就可以帮助你。

  对于什么是一个好的测试,GTest如何来帮助实现这个目标,我们的观点如下:

  测试必须是独立并且可重复的。如果某个测试的通过还是失败依赖于其它测试的执行结果,那么调试它将是非常困难的。GTest通过在不同的项目下分别执行测试使得它们相互隔离。当某个测试失败后,GTest允许你单独执行它以便快速调试。

  测试的组织必须很好的反映测试代码的结构。GTest以测试用例为单位把那些能共享相同数据和代码的测试组织起来。这种常见的模式使得我们可以很方便的识别和维护测试。当人们切换项目在新的代码基础上工作时,这种一致性会显得特别有帮助。

  测试必须可移植和可重用。开源社区的很多代码都是平台中立的,所以它们的测试也必须平台中立。GTest可以在不同的操作系统上工作,使用不同的编译器,支持或不支持异常,所以GTest可以很容易的在不同配置上工作。(注意:当前的发行版只包含Linux的构建脚本,我们正努力工作以支持其它平台。)

  一个测试失败后必须提供尽可能多的提示信息。GTest不会因为一个失败就停止继续工作。它仅仅停止当前测试并且继续执行后续的测试。你还可以设置测试在遇到非致命失败时继续执行并打印相关信息。通过这种方法,你可以在一个“执行-编辑-编译”周期中发现和修复多处bug

  测试框架必须把测试编写者从繁重的家常事务中解脱出来以集中精力于测试本身。GTest自动维护和跟踪所有定义的测试,不需要你为了运行测试而去手工枚举所有测试。

  测试必须迅速。使用GTest,你可以在不同测试之间使用共享的资源,而只需要做一次set-up/tear-down的工作,并且测试和测试之间相互独立。

  因为GTest使用流行的xUnit架构,只要你熟练使用JUnit或PyUnit就一定会感到非常亲切。如果以前没玩过的话,只要花10分钟就可以上手了。好吧,我们继续!

  让GTest学习打印自定义对象

  当一个断言比如EXPECT_EQ()失败时,GTest会打印它的参数来帮你调试。它依靠用户可扩展值打印机来实现此功能。

  这个打印机了解如何打印C++的内建类型,原生数组,STL容器和任何支持"<<"操作符的类型。对于其它类型,它会打印原始的字节然后等您老自己意会。

  前面提到这个打印机是可扩展的。这表明除了打印原始字节,对于你感兴趣的类型显然可以做得更好。怎么做呢?请自己实现"<<"操作符。参考以下代码:

复制代码

  #include

  namespace foo {

  class Bar { ... }; // We want Google Test to be able to print instances of this.

  // It's important that the << operator is defined in the SAME

  // namespace that defines Bar. C++'s look-up rules rely on that.

  ::std::ostream& operator<<(::std::ostream& os, const Bar& bar) {

  return os << bar.DebugString(); // whatever needed to print bar to os

  }

  } // namespace foo

复制代码

  有时候这个方案也许行不通。你的团队认为使用"<<"操作符对于Bar类是个不好的风格,或者Bar类已经支持"<<"操作符但是实现了其它功能。在这种情况下,你可以定义一个PrintTo()函数作为替代方案:

复制代码

  #include

  namespace foo {

  class Bar { ... };

  // It's important that PrintTo() is defined in the SAME

  // namespace that defines Bar. C++'s look-up rules rely on that.

  void PrintTo(const Bar& bar, ::std::ostream* os) {

  *os << bar.DebugString(); // whatever needed to print bar to os

  }

  } // namespace foo

复制代码

  如果"<<"操作符和PrintTo()同时被定义了,GTest会优先使用后者。这使得你可以自定义GTest如何输出你的值而不依赖于"<<"操作符的行为。

  如果你想调用GTest的打印机来打印一个值x,直接调用::testing::PrintToString(x),这个函数会返回std::string。

  vector > bar_ints = GetBarIntVector();

  EXPECT_TRUE(IsCorrectBarIntVector(bar_ints))

  << "bar_ints = " << ::testing::PrintToString(bar_ints);

  基本概念使用GTest你肯定会接触到断言这个概念。断言是用来判断某个条件是否为真。一个断言的结果可以是通过,也可以是非致命失败或致命失败。如果发生了一个致命失败,当前函数就会立刻退出,不然函数还是会继续执行到正常结束。测试使用断言来判断测试代码的行为。如果测试崩溃了或者断言失败,那么这个测试就失败了,不然就是通过。一个测试用例包含一个或多个测试。你必须用测试用例把你的测试进行分组以反映测试代码的结构。当某个测试用例中的多个测试共享一些对象或程序时,你可以把这些对象和程序放进test fixture类。一个测试程序可以包含多个测试用例。我们现在开始讲解如何编写一个测试程序,先从单个断言开始,然后逐步到测试和测试用例。

原文转自:http://www.cnblogs.com/panda_lin/p/gtest_primer_ch_03_basic_concepts.html