Linux 下使用Google Test

最近一直在搭建 CI 框架,必不可少的就是需要有 Unit Test 的工具。

我们的代码90%都是C和C++,同时需要支持 Red Hat, SUSE, Windows和 Solaris 平台(好在Solaris 客户少了,对该版本的支持即将结束)。我们最终选定 Google Test 来做 UT。

首选从 github (https://github.com/google/googletest.git)上下载了 gtest 的源码.

按照网上大多数人的建议,cmake..... 本以为会很顺利的。结果却没有想象的那么简单。

查看 make 错误输出,发现提示 nullptr 未定义。OK, 了解了,这是因为 gtest 支持C++11。嗯,改吧...

这里走了一些弯路,之前我们用到的 gcc, git 这些都是官网上拿到最新版代码,按照提示直接 make, install。。我们想着 gtest 也这么做吧.

Gtest 的官网说了google 自己是没有用cmake 的,cmake 都是由社区贡献 。改cmake模板确实很麻烦,研究了一下 gtest 源码,发现没有必要这么做。

查看gtest 下 src 目录,发现有一个 gtest-all.cc文件。文件基本 include 目录下所有 .cc 的文件。gtest_main.cc 这里有 main 函数。那我们应该只需要编译这两个 cc 文件就行。

这是我的步骤:

1.  g++ 编译 gtest-all.cc 文件,生成 gtest-all.o 文件

2.  g++ 编译 gtest_main.cc 文件,生成 gtest_main.o 文件

3. 链接 gtest-all.o 为共享库 libgtest.so, 链接 gtest_main.o 为静态库gtest_main.a

4. libgtest.so 所在目录加到 LD_LIBRARY_PATH 变量中。

g++ -Wall -c -fPIC -std=c++11 -I./include -I./ -c ./src/gtest-all.cc

g++ -I ../include -g -Wall -Wextra -pthread -c gtest_main.cc -std=c++11

g++ -shared -fPIC -o libgtest.so gtest-all.o

ar rv gtest_main.a gtest_main.o  

接下来就是使用 gtest了。

写一个简单函数先测试一下功能吧。这是我的目标函数,返回数的绝对值。

int myAbs(int x)
{
    return x > 0 ? x : -x;
}

测试目标函数,我至少需要三个case,以下是我的Utest 代码,正数返回

#include <gtest/gtest.h>
TEST(MyABSTest, PosNumber)
{
    EXPECT_EQ(2, myAbs(2));
    ASSERT_FALSE(myAbs(2) == -2);
}
TEST(MyABSTest, NegNumber)
{
    EXPECT_EQ(2, myAbs(-2));   ASSERT_NE(myAbs(-2),-2); } TEST(MyABSTest, Zero) { EXPECT_EQ(0, myAbs(0)); }

编译代码的sample

-L/$(GTEST_LIB)/lib -lgtest -lpthread $(STATIC_LIBPATH)/gtest_main.a

需要需要指定 gtest 的共享库,以及 gtest_main.a 的静态库,不需要手动写 main 函数。

输出如下

Linux 下使用Google Test

 这种纯文本输出肯定不是我想要的,因为我最后需要把输出结果放到Jenkins上的,所以需要输出为 xml. 执行参数为 ”--gtest_output=xml”

如果只简单指定输出为 xml, 会生成默认输出结果 test_detail.xml。也可以使用 "test_detail.xml:./testresult.xml" 在当前路径下生产 testresult.xml 的输出文件。

<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="3" failures="0" disabled="0" errors="0" time="0.001" timestamp="2020-03-28T12:03:49" name="AllTests">
  <testsuite name="MyABSTest" tests="3" failures="0" disabled="0" errors="0" time="0" timestamp="2020-03-28T12:03:49">
    <testcase name="PosNumber" status="run" result="completed" time="0" timestamp="2020-03-28T12:03:49" classname="MyABSTest" />
    <testcase name="NegNumber" status="run" result="completed" time="0" timestamp="2020-03-28T12:03:49" classname="MyABSTest" />
    <testcase name="Zero" status="run" result="completed" time="0" timestamp="2020-03-28T12:03:49" classname="MyABSTest" />
  </testsuite>
</testsuites>

这样三个case 的 xml 格式输出正常了。

实际中,我需要为case添加一些描述信息,这样可以让后续维护的人了解每一个case大致都做些什么。

这时我需要修改我的测试代码,为其添加一些属性,代码如下

#include <gtest/gtest.h>
#include "MyABS.h"

TEST(MyABSTest, PosNumber)
{
        this->RecordProperty("Description", "Pos number n return n");
        EXPECT_EQ(2, myAbs(2));
        ASSERT_FALSE(myAbs(2) == -2);
}
TEST(MyABSTest, NegNumber)
{
        this->RecordProperty("Description", "Neg number n return -n");
        EXPECT_EQ(2, myAbs(-2));
        ASSERT_NE(myAbs(-2),-2);
}
TEST(MyABSTest, Zero)
{
        this->RecordProperty("Description", "Zero return Zero");
        EXPECT_EQ(0, myAbs(0));
}

输出xml 结果如下

<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="3" failures="0" disabled="0" errors="0" time="0" timestamp="2020-03-28T12:12:29" name="AllTests">
  <testsuite name="MyABSTest" tests="3" failures="0" disabled="0" errors="0" time="0" timestamp="2020-03-28T12:12:29">
    <testcase name="PosNumber" status="run" result="completed" time="0" timestamp="2020-03-28T12:12:29" classname="MyABSTest">
        <properties>
                <property name="Description" value="Pos number n return n"/>
        </properties>
    </testcase>
    <testcase name="NegNumber" status="run" result="completed" time="0" timestamp="2020-03-28T12:12:29" classname="MyABSTest">
        <properties>
                <property name="Description" value="Neg number n return -n"/>
        </properties>
    </testcase>
    <testcase name="Zero" status="run" result="completed" time="0" timestamp="2020-03-28T12:12:29" classname="MyABSTest">
        <properties>
                <property name="Description" value="Zero return Zero"/>
        </properties>
    </testcase>
  </testsuite>
</testsuites>

好了, gtest 简单用法先介绍到这里了。会用 gtest 后,我们还需要学会 gmock。我会在下一篇文章中介绍 gmock 的使用。

相关推荐