gtest学习笔记(一)

gtest使用了xUnit的框架,xUnit的框架的公共的特点是包含了一下几个元素:

  • test case:测试用例集
  • test:测试用例
  • test fixture:构造测试用例的公共前提条件或状态
  • test setup:构造测试的前提条件或状态
  • test teardown:还原到测试执行前的状态
  • assertion:断言,用于检查

gtest的源代码结构如下图:

image

简单说一下目录结构:

msvc是针对visual studio创建的gtest的工程文件,make文件夹下是针对linux的Makefile,xcode和codegear不用解释了。script文件夹下是一些脚本用于产生测试用例的,test下是测试gtest框架本身的一些代码。其中源代码包含在include、src两个文件夹中着重看一下src文件夹中的这些源文件。

image

gtest.cc文件实现了gtest的框架和对外接口

gtest_main.cc定义的main函数

gtest-all.cc包含了所有源文件

gtest-death-test.cc实现了死亡测试相关的内容

gtest-filepath.cc

gtest-port.cc定义了一写平台移植相关的内容

gtest-printers.cc

gtest-test-part.cc

gtest-typed-test.cc定义了参数化测试的内容

gtest-internal-inl.h是gtest内部使用的,用户不应该包含该头文件,否则会编译出错

 

我们看代码一般习惯从main函数开始入手,我们就先从main函数说起吧,gtest为我们提供标准的main函数,在src/gtest_main.cc文件中,内容如下。

#include <stdio.h>

#include "gtest/gtest.h"

GTEST_API_ int main(int argc, char **argv)
{
    printf("Running main() from gtest_main.cc\n");
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

这是一个非常简单的main函数,先看库文件,gtest.h库文件定义了gtest向外提供的所有API,这个库中包括两个命名空间

testing:包含了开放给用户使用的API。

testing::internal:定义了gtest的一些内部实现。

InitGoogleTest()函数是gtest对外提供的一个接口函数,里面封装了一个内部的实现,代码很简单

void InitGoogleTest(int *argc, char **argv)
{
    internal::InitGoogleTestImpl(argc, argv);
}

InitGoogleTestImpl()是定义在internal中的实现,注意gtest中很多地方使用了这样的形式,对外接口只是简单的封装,具体实现在internal中。这样做的好处也是明显的,对外提供统一稳定的接口,即使内部实现产生大的变动时,也不会影响到建立在gtest框架上的程序的编译和执行。

InitGoogleTest()的主要功能是完成参数的解析和创建一个UnitTest的实例,关于UnitTest将在后面讲到。并且InitGoogleTest()在一个程序中只能调用一遍,因为在internal里定义了一个全局变量来计数InitGoogleTest()运行的次数,运行InitGoogleTest()时会先检查这个变量,超过1则直接返回。

InitGoogleTestImpl()方法中定义了初始化共做主要代码如下:

template <typename CharType>
void InitGoogleTestImpl(int *argc, CharType **argv)
{
    g_init_gtest_count++;

    // We don't want to run the initialization code twice.
    if (g_init_gtest_count != 1) return;

    if (*argc <= 0) return;

    internal::g_executable_path = internal::StreamableToString(argv[0]);

#if GTEST_HAS_DEATH_TEST

    g_argvs.clear();
    for (int i = 0; i != *argc; i++)
    {
        g_argvs.push_back(StreamableToString(argv[i]));
    }

#endif  // GTEST_HAS_DEATH_TEST

    ParseGoogleTestFlagsOnly(argc, argv);
    GetUnitTestImpl()->PostFlagParsingInit();
}

argv是传入的命令行参数,gtest支持命令行参数,InitGoogleTestImpl()中的ParseGoogleTestFlagsOnly()对参数进行了解析并设置了相应个flag并不做其他的初始化工作,而GetUnitTestImpl()->PostFlagParsingInit()通过UnitTestImpl类中的PostFlagParsingInit()方法根据相应的flag初始化gtest。

下面着重说一下UnitTest,UnitTest也是一个对外的接口类,其功能就是负责维护和执行所有的test。他是一个singleton,只能通过GetInstance()方法获得唯一的实例,它的内部有一个指向UnitTestImpl类的指针,UnitTestImpl是定义在internal中的UnitTest的实现,UnitTestImpl将UnitTest声明为友元类,这样UnitTest就可以访问UnitTestImpl中的成员来完成功能。

posted @ 2011-12-27 00:13  wulax  阅读(2088)  评论(1编辑  收藏  举报