zoukankan      html  css  js  c++  java
  • GoogleTest初探(0)

    单元测试是一种保证代码质量的手段。程序员可以通过写单元测试来保证自己写的代码的功能正确。

    本人所在公司使用GoogleTest测试框架来进行单元测试。虽然现在在公司的工程代码中写单元测试已经驾轻就熟,但是只是知其然不知其所以然,所以再此对Google Test测试框架进行一个全面的了解与学习。

    本文只涉及Google Test的使用,不涉及对其源码的学习与解读。

    Linux环境搭建Google Test测试环境

    Google Test托管在github上,先通过git把Google Test拉取到本地

    git clone https://github.com/google/googletest.git

    Google Test 提供了多平台的构建方式,在Linux上推荐使用cmake来编译

    cd googletest
    cmake .

    编译完成之后生成静态库,以后编译自己的单元测试需要链接这些静态库

    最后,安装,将头文件和编好的库文件放在系统指定目录下,此步骤需要root权限

    make install

    安装完成之后,可以尝试编译运行Google Test自带的sample

    cd googletest/googletest/make
    make
    ./sample1_unittest

    运行结果如图所示:

    想要从头开始学些如何使用Google Test,去研究一下googletest/googletest/samples下的所有测试用例和googletest/googletest/doc目录下的指导文档,把这些搞清楚了,也就初步掌握了Google Test了。

    基本测试

     

    //myGtest.cpp
    #include <gtest/gtest.h>
    
    int add(int a, int b) //待测试函数
    {
        return a + b;
    }
    
    TEST(TestAdd, normal)//单元测试
    {
        EXPECT_EQ(3, add(1, 2));
        EXPECT_EQ(4, add(1, 2));
    }
    
    int main(int argc, char **argv)//初始化GoogleTest并运行所有单元测试
    {
        testing::InitGoogleTest(&argc, argv);
        return RUN_ALL_TESTS();
    }

    编译:

    g++ myGtest.cpp -lgtest -lpthread -o myGtest

    注意不仅要链接libgtest.a还要链接libpthread.a

    运行结果:

    可以看到测试结果,符合add函数的预期行为。

    对于基本测试行为,必须包含以下的要素:

    1. 测试文件必须包含头文件 gtest/gtest.h;

    2. 单元测试函数使用宏 TEST,没有返回类型,有两个参数:第一个测试是测试用例名,第二个参数是本测试名;

    3. 测试内容和逻辑需要你自己编写,GoogleTest提供了一系列的宏(类似于安断言)来判断你的代码是否符合预期结果;

    4. 需要有一个main函数来初始化并执行所有测试,这个main函数的写法是固定的(由于其是固定的,也可以不写main函数,Google Test提供了一个写好的main 函数只要在链接时链接libgtest_main.a即可),RUN_ALL_TESTS()来执行所有的测试。返回值为0说明全部测试通过,1则说明有失败的测试。

    Test Fixtures

    有些地方也翻译作测试夹具,我感觉找不到对其合适的翻译。

    就是将有相同的流程或使用相同数据的测试用例聚合起来,共享同一套流程或同一份数据,这套流程或数据会在每个测试用例运行之前和之后执行固定的操作。

    待测试类:

    //MyClass.hpp
    class MyClass
    {
    public:
        int add(int a, int b)
        {
            return a + b;
        }
    
        int plus(int a, int b)
        {
            return a * b;
        }
    };

    测试:

    //myGtest.cpp
    #include <gtest/gtest.h>
    #include <iostream>
    #include "MyClass.hpp"
    
    class TestMyClass : public testing::Test  //test fixture类
    {
    protected:
        void SetUp() override//每个测试运行前调用
        {
            std::cout<<"test start"<<std::endl;
        }
        void TearDown() override//每个测试运行后调用
        {
            std::cout<<"test done"<<std::endl;
        }
        MyClass mc;
    };
    
    TEST_F(TestMyClass, testAdd)//测试用例1
    {
        EXPECT_EQ(3, mc.add(1, 2));
    }
    
    TEST_F(TestMyClass, testPlus)//测试用例2
    {
        EXPECT_EQ(2, mc.plus(1, 2));
    }
    
    int main(int argc, char **argv)
    {
        testing::InitGoogleTest(&argc, argv);
        return RUN_ALL_TESTS();
    }

    运行结果:

    可以看到测试结果,符合MyClass类的类方法的预期。并且在测试开始和结束时打印出来我们想要的提示信息

    当一个测试执行时会发生以下事件:

    1. GTest构造TestMyClass对象(我们称之为t1)。

    2. t1.SetUp()函数初始化t1。

    3. t1的第一个测试testAdd执行。

    4. 在测试执行完后调用t1.TearDown()清理现场。

    5. t1被析构。

    6. 以上步骤重复一遍,这一轮是执行测试testPlus

    使用Test Fixtures可以讲一些流程重复或者数据重用的测试用例聚合起来,更方便编写和维护

    对于Test Fixtures而言,具有一下几个要素:

    1. 从::testing::Test集成一个类。根据我们希望访问子类的fixture成员的权限,限定为protected或public

    2. 在类中,定义任何你想使用的对象

    3. 如果需要,实现默认的构造函数或SetUp()函数来为每个测试准备数据

    4. 如果需要,实现析构函数和TearDown函数来释放SetUp()函数分配的资源

    5. 如果需要,请自定义测试需要共享的函数

    6. 使用时,用TEST_F代替TEST(在使用TEST_F前必须先定义好Test Fixtures 类)

    7. TEST_F无返回值,有两个参数,第一个是Test Fixtures 类名,第二个是测试名

    相关链接:

    https://github.com/google/googletest/blob/master/googletest/docs/primer.md

    https://www.cnblogs.com/panda_lin/p/gtest_primer.html

  • 相关阅读:
    caffe简单介绍
    良好地去规划自己的学习
    计算机视觉开篇---读史可以明智
    Oracle的闪回操作
    数据库的管理
    oracle dblink结合同义词的用法 PLS-00352:无法访问另一数据库
    一次导如数据库时主表数据丢失的解决过程
    Oracle函数的使用
    MinGW和MSYS的自动安装 【转】
    Oracle表的管理
  • 原文地址:https://www.cnblogs.com/duan-shui-liu/p/10731302.html
Copyright © 2011-2022 走看看