googletest
谷歌 c + + 测试框架
|
搜索 内搜索: 所有 wiki 页面 特色的页 当前页 不推荐使用的页 对于
|
V1_6_Primer
入门谷歌 c + + 测试框架
简介: 为什么谷歌 c + + 测试框架?谷歌 c + + 测试框架可以帮助你写出更好的 c + + 测试。 无论是否您工作在 Linux 上,Windows 或 Mac,如果您编写 c + + 代码,谷歌测试可以帮助你。 是什么让一个好的测试,和谷歌 c + + 测试框架如何适应呢?我们相信:
由于谷歌 c + + 测试框架基于流行 xUnit 建筑,你会感觉右在家里如果您使用过 JUnit 或前的 PyUnit。如果不是,它将带你了解的基本知识和开始约 10 分钟。所以我们去吧 ! 注:我们有时称为 Google c + + 测试框架非正式谷歌测试. 建立一个新的测试项目要编写一个使用谷歌测试的测试程序,您需要将谷歌测试编译成库和链接您的测试与它。对于一些受欢迎的生成系统生成文件,我们提供: msvc /Visual studio, xcode /为 Mac Xcode,使 /为 GNU,指令 / Borland c + + 生成器,和 autotools 脚本 (已过时) 和CMakeLists.txt的 CMake (推荐) 谷歌测试的根目录中。如果您生成系统不在此列表中,您可以看一看学习 Google 测试应如何编译使/生成文件(基本上您要编译src/gtest-all.cc与GTEST_ROOT和GTEST_ROOT/包含在标题搜索路径中,其中GTEST_ROOT是 Google 测试根目录)。 一旦您将能够编译谷歌测试库,应创建一个项目,或您的测试程序生成目标。请确保你有GTEST_ROOT/包含标题搜索路径中,以便您的测试进行编译时,编译器可以找到"gtest/gtest.h" 。设置您的测试项目与谷歌测试库链接 (例如,在 Visual Studio 中,这通过在gtest.vcproj上添加依赖项). 如果您还有问题,看看如何测试 Google 测试生成并将其用作示例。 基本概念在使用谷歌测试时,你开始通过编写断言,哪些语句,检查是否一个条件为真。断言结果可以成功、非致命故障或致命故障。如果发生致命故障,它将中止当前的功能 ;否则,程序继续正常。 测试使用断言来验证测试的代码的行为。如果测试崩溃或已失败的断言,那么它将失败;否则为它会成功. 测试用例包含一个或多个测试。您应将测试用例反映测试代码的结构组成您的测试。当多个测试的测试用例需要共同的对象和子例程时,你能把它们测试夹具的类。 测试程序可以包含多个测试用例。 我们现在将说明如何编写一个测试程序,开始在个别论断一级和建立测试和测试用例。 断言谷歌测试断言是类似于函数调用的宏。您通过使其行为的断言测试类或函数。当断言失败时,谷歌测试打印断言的源文件和行号的位置,连同失败消息。您也可以提供自定义失败消息,将追加到谷歌测试邮件。 断言测试同样的事情,但有不同的效果,对当前函数的成对出现。ASSERT_ *版本生成失败时,致命故障和中止当前函数。EXPECT_ *版本生成非致命的失败,不中止当前函数。EXPECT_ *通常首选,因为它们允许多个测试中报告故障。但是,您应该使用ASSERT_ *如果不合情理,则断言失败后继续。 由于失败ASSERT_ *从当前函数立即返回,可能会跳过清理代码后,它可能会导致空间泄漏。取决于漏油的性质,它可能会或可能不值得修复-所以记住这一点如果你除了断言错误堆检查器错误。 若要提供自定义失败消息,只是流它成宏使用<<运算符或这类商户的序列。示例: ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length"; 任何可以传输到ostream的东西可以进行流式传输到断言宏 — — 尤其是 C 字符串和字符串对象。如果宽字符串 (wchar_t *, TCHAR *在UNICODE模式下,在 Windows 中或std::wstring) 流入到一个断言,它将被翻译为 utf-8 打印时。 基本的断言这些断言做真/假的基本条件测试。
请记住,当他们失败时, ASSERT_ *收益率出现致命故障和返回从当前函数,而EXPECT_ *产量为非致命的失败,从而能够继续运行功能。在任一情况下,断言失败意味着它包含测试失败。 可用性: Linux、 Windows、 mac。 二进制比较本节介绍比较两个值的断言。
故障时,事件中谷歌测试打印在val1和val2 。ASSERT_EQ * EXPECT_EQ * (及其他所有我们稍后介绍的平等断言),您应将您要测试的实际位置的表达式放并把其预期的价值放在预期,作为谷歌测试失败的消息非常适合于本公约。 值参数必须是可比的说法比较运算符的否则你会编译器错误。我们需要支持的参数使用<<以来 v1.6.0 运算符的流ostream,但它已不再需要 (如<<是支持,它将调用,则断言失败时打印参数 ; 否则将尝试将其打印出来的最佳方法,它可以在谷歌测试。更多详细信息以及如何自定义参数的打印,请参阅此 Google 模仿食谱.). 如果您定义相应的比较运算符,这些断言可以使用用户定义的类型,但仅限于 (例如= =, <,等等)。如果定义了相应的运算符,则更倾向于使用ASSERT_*()宏,因为他们会打印出结果的比较,但以及两个操作数不只。 参数总是进行一次评估。因此,它是有副作用的参数确定。然而,与任何普通的 C/c + + 函数,一样的参数的计算顺序是未定义 (即编译器是自由选择任何顺序) 和您的代码不应依赖于任何特定的参数计算顺序。 ASSERT_EQ()没有指针的指针平等。如果使用两个 C 字符串,它测试如果它们在相同的内存位置,如果它们具有相同的值。因此,如果您想通过值比较 C 字符串 (例如const char *),使用ASSERT_STREQ() ,将在稍后介绍的。特别是,声称是 C 字符串为空,使用ASSERT_STREQ NULL c_string) 。不过,若要比较两个字符串对象,您应使用ASSERT_EQ. 这一节中的宏 (字符串和wstring这两个狭窄和宽字符串对象的工作). 可用性: Linux、 Windows、 mac。 字符串比较在此组中的断言,比较两个C 字符串。如果要比较两个字符串对象,请使用EXPECT_EQ、 EXPECT_NE、 等代替。
请注意断言名称中的"案例"意味着忽略大小写。 * STREQ *和* STRNE *也接受宽的 C 字符串 (wchar_t *)。如果两个宽字符串比较失败,其值将打印为 UTF 8 窄字符串。 一个空字符串和NULL指针被视为不同. 可用性: Linux、 Windows、 mac。 另请参阅: 更多的字符串比较特技 (子串、 前缀、 后缀,和正则表达式匹配,例如),请参见高级谷歌测试指南. 简单的测试要创建一个测试:
TEST(test_case_name, test_name) { TEST()参数从一般转到特定。第一个参数是测试用例的名称,第二个参数是内测试用例的测试的名称。这两个名称必须是有效的 c + + 标识符,它们不应包含下划线 (_)。测试的完整名称由其包含测试用例和其个人名称组成。来自不同测试用例的测试可以有个别的名称相同。 例如,让我们看一个简单的整数函数: int Factorial(int n); // Returns the factorial of n 此函数的测试用例可能类似于: // Tests factorial of 0. 谷歌测试组的测试结果的测试用例,所以逻辑上相关的测试应在同一测试用例 ;换句话说,他们TEST()的第一个参数应是相同的。在上面的示例中,我们有两个测试, HandlesZeroInput和HandlesPositiveInput,属于同一个测试用例FactorialTest. 可用性: Linux、 Windows、 mac。 测试夹具: 使用相同的数据配置多个测试如果您发现自己相似的数据写入两个或更多的测试操作,您可以使用测试夹具。这样,您就可以重复使用的对象的多个不同测试相同的配置。 若要创建夹具,只是:
使用时夹具,使用TEST_F()的TEST()而不是因为它允许您访问对象和测试夹具的子例程: TEST_F(test_case_name, test_name) { 像TEST(),第一个参数是测试用例的名称,但对于TEST_F() ,这必须测试夹具类的名称。您可能已经猜到: _F是夹具。 不幸的是,在 c + + 宏系统不允许我们能够创建一个单一的宏,可以处理这两种类型的测试。使用错误的宏将导致编译器错误。 此外,在TEST_F()中,在使用之前必须首先定义测试夹具类,否则你会编译器错误"' 虚拟类声明外'"。 用TEST_F()定义的每个测试中,Google 测试将:
作为一个例子,让我们写测试 FIFO 队列类命名队列中,具有以下接口: template <typename E> // E is the element type. 首先,定义夹具的类。按照约定,,你应该给它生成器美孚在哪里类名称正在进行测试。 class QueueTest : public ::testing::Test { 在这种情况下,由于我们不需要每个测试,除已做的析构函数之后进行清理,则不需要TearDown() 。 现在我们会编写测试使用TEST_F()和这种装置。 TEST_F(QueueTest, IsEmptyInitially) { 上述使用了ASSERT_ *和EXPECT_ *断言。经验法则是使用EXPECT_ *当您想要继续断言失败后,透露更多的错误,并使用ASSERT_ *时继续后失败没什么意义的测试。例如,出列测试中的第二个说法是ASSERT_TRUE (n! = NULL),就像我们要取消引用指针n后,这将导致 segfault n为NULL时. 当这些测试运行时,会发生下列情况:
可用性: Linux、 Windows、 mac。 注: 谷歌测试自动保存所有谷歌测试标志时测试对象构造,并还原它们时它破坏。 调用测试TEST()和TEST_F()隐式使用谷歌测试注册他们的测试。所以,不同于与很多其他 c + + 测试框架,你不必为了运行它们 re-list 定义的所有测试。 定义您的测试之后, 您可以运行它们的RUN_ALL_TESTS() ,它返回0 ,如果所有的测试都成功或1否则。请注意RUN_ALL_TESTS()运行您的链接单元中的所有测试— — 它们可以从不同的测试案例或甚至不同的源文件。 当调用, RUN_ALL_TESTS()宏:
此外,如果文本夹具的构造函数生成致命故障在步骤 2 中,是没有意义的步骤 3-5,因此被跳过。同样,如果第 3 步生成一个致命的失败,则将被跳过第 4 步。 重要提示: 您一定不能忽略的返回值RUN_ALL_TESTS(),或将给你gcc编译器错误。这种设计的理由是自动化测试服务确定是否对其退出代码,不是在它的标准输出/stderr 输出 ; 测试已通过基于因此你的main ()函数必须返回值的RUN_ALL_TESTS(). 此外,您应调用RUN_ALL_TESTS()唯一一次。叫它不止一次冲突与一些高级功能 (如线程安全死亡测试) 的谷歌测试,因此不支持。 可用性: Linux、 Windows、 mac。 编写函数 main)您可以从这个样板启动: #include "this/package/foo.h" :: Testing::InitGoogleTest()函数解析命令行,因为谷歌测试标志,并删除所有认可的标志。这允许用户控制通过各种标志,我们将介绍在AdvancedGuide的测试程序的行为。您必须在调用RUN_ALL_TESTS()之前, 调用此函数或标志不会被正确初始化。 在 Windows 上, InitGoogleTest()同样适用于宽字符串,因此它可以用于UNICODE模式以及在编译的程序。 但也许你认为编写所有那些 main () 函数是太多的工作吗?我们完全同意你,这就是为什么 Google 测试提供 main () 的基本实现。如果它适合您的需要,然后只是链接您的测试与 gtest_main 库,你是要走好。 对于 Visual c + + 用户的重要说明如果你把你的测试放在图书馆,你的main ()函数是在另一个库或.exe 文件中将不会运行这些测试。原因是 Visual c + + 中的bug 。当您定义您的测试时,谷歌测试创建某些注册他们的静态对象。这些对象不从其他地方引用,但仍然应该运行它们的构造函数。Visual c + + 链接器看到什么库中引用的其他地方时它会引发图书馆。你要从主程序从丢弃它保持链接器的测试引用您的库。这里是如何做这件事。某处代码库中声明的函数: __declspec(dllexport) int PullInMyLibrary() { return 0; } 如果你把你的测试放在静态库 (而不是 DLL) 然后__declspec(dllexport)则不需要。现在,在 main 程序中写一段代码,它调用该函数: int PullInMyLibrary(); 这会让你的测试引用,会使他们自行注册在启动时。 此外,如果您在静态库中定义您的测试,添加/OPT:NOREF主程序链接器选项。如果您使用 MSVC + + IDE,转到您的.exe 项目属性/配置属性/链接器/优化和设置的引用设置为保持未引用数据 (/ 选择: NOREF)。这将使 Visual c + + 链接器丢弃单个符号生成最终的可执行文件从您的测试。 不过还有一个更多陷阱。如果您使用谷歌测试静态库 (即如何定义的 gtest.vcproj) 作为您的测试也必须位于一个静态库。如果你要让他们在 DLL 中,您必须更改将建成一个 DLL 以及谷歌测试。否则为你的测试将不会正确运行,或者将不能运行。普遍的结论是: 使您的生活更轻松 — — 图书馆不写你的测试 ! 从这里去哪里恭喜 !您已经了解谷歌测试基础。可以开始编写和测试运行谷歌测试、 阅读一些样本,或继续AdvancedGuide,它描述了许多更有用的谷歌测试功能。 已知的局限性谷歌测试被为了是线程安全的。执行是线程安全的pthreads图书馆在哪里可用的系统上。它目前是不安全使用谷歌测试断言从两个线程同时在其他系统 (如 Windows)。在大多数的测试中这不是问题,通常所断言的事,主线程。如果你想帮助,您可以在您的平台gtest port.h执行必要的同步基元志愿者。 |
|||||||||||||||||||||||||||||||||||||||||||||