如何将 Google 测试与通过自动工具构建的项目一起使用

How can I use Google Test with my project that builds via autotools?

本文关键字:构建 工具 项目 一起 Google 测试      更新时间:2023-10-16

似乎有一些答案有点道理,但我不知道如何执行。而且我还没有找到一个全面的答案。

第一个问题

Google Test不应该是一个已安装的库,它应该与项目一起构建。(请参阅常见问题解答。据我所知,这意味着 Google 测试库是我的单元测试的依赖项,应该在我第一次在我的项目中运行"make check"时构建。这应该在某个目录中构建谷歌测试库。我不知道该怎么做。它提到了一些已弃用的自动工具脚本,我不确定他们在说什么或如何正确地将我的构建指向它。

第二个问题

假设构建成功,如何编写使用本地编译的 Google 测试版本来运行测试的测试?我假设我的测试目录中放了一堆 Makefile.am 命令。但它们是什么?使用谷歌测试的单元测试的例子是什么?

我已经解决了令我满意的问题!我现在将完全继续前进。这基本上是要求教程。必须做出很多决定,希望合乎逻辑,以便谷歌测试与自动化工具很好地吻合。所以我提前为冗长的答案道歉,但所有细节都应该在那里。

第一个问题

为了理解答案,这个问题需要稍微改写一下。我们正在将 Google Test 编译为一个库,我们的测试代码将链接到该库。不会安装库。我们想问的问题是

"我们如何配置自动工具以将Google Test编译为库。我们的测试代码可以链接到哪个?

为此,我们需要下载Google测试并将其放入我们的项目中。我使用 Github,所以我通过在项目的根路径中添加一个子模块来做到这一点:

$ git submodule add git@github.com:google/googletest.git
$ git submodule init
$ git submodule update

这会将googletest下载到我的项目根目录中:

/:
    Makefile.am
    configure.ac
    src/:
        (files for my project)
    tests/:
        (test files)
    googletest/:
        googletest/:
            include/:
                (headers, etc., to be included)
                gtest/:
                    gtest.h
            m4/:
                (directory for m4 scripts and things)
            src/:
                (source files for Google Test)

我需要按照说明进行编译。我只希望 Google 测试库建立在运行 make check 上,所以我将使用check_LTLIBRARIES。我将以下内容添加到我的测试 Makefile.am/tests 中:

check_LTLIBRARIES = libgtest.la
libgtest_la_SOURCES = ../googletest/googletest/src/gtest-all.cc
libgtest_la_CPPFLAGS = -I$(top_srcdir)/googletest/googletest/include -I$(top_srcdir)/googletest/googletest
libgtest_la_LDFLAGS = -pthread

这需要在 configure.ac 中启用子目录对象。这是通过将其添加到AM_INIT_AUTOMAKE行来实现的。我还需要在 AC_CONFIG_FILES 中包含生成文件。我们还想使用 libtool,因为我们正在编译库文件(稍后我将解释为什么以及如何工作)。要使用libtool,我们LT_INIT添加AM_PROG_AR。我们希望 autoreconf 将 m4 宏安装到/m4,然后我们希望 automake 找到它们,所以我们需要AC_CONFIG_MACRO_DIRS。我的 configure.ac 更新了行:

AM_INIT_AUTOMAKE([-Wall -Werror subdir-objects])
...
AM_PROG_AR
LT_INIT
AC_CONFIG_MACRO_DIRS([m4])
...
AC_CONFIG_FILES([Makefile
                 src/Makefile
                 tests/Makefile
                 ])

我还需要在我的/Makefile.am 中包含子目录和指向/m4 宏目录中宏的行:

ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src tests

这做了什么?Libtool 已启用 AM_PROG_AR 和 LT_INIT。check_LTLIBRARIES意味着我们将使用 libtool 来创建一个名为 libgtest.la 的便利库。启用子目录对象后,它将被内置到/tests 目录中,但不会安装。这意味着,每当我们想要更新测试时,我们都不必重新编译 Google 测试库 libgtest.la。这将节省测试时间,并帮助我们更快地迭代。然后,我们将希望稍后在更新单元测试时针对它编译单元测试。该库只会在运行时编译 make check ,如果我们只想makemake install,则通过不编译它来节省时间。

第二个问题

现在,第二个问题需要改进:你如何(a)创建一个链接到谷歌测试库的测试(b),从而使用它们?这些问题有点交织在一起,所以我们立即回答它们。

创建测试只需将以下代码放入位于 /tests/gtest.cppgtest.cpp 文件中:

#include "gtest/gtest.h" // we will add the path to C preprocessor later
TEST(CategoryTest, SpecificTest)
{
    ASSERT_EQ(0, 0);
}
int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

这仅运行简单测试 0=0。要为您的文库创建测试,您需要阅读入门。您会注意到我们(还)不需要标头。我们正在链接到文件"gtest/gtest.h",因此我们需要确保我们告诉 automake 包含一个具有 gtest/gtest.h 的目录。

接下来,我们需要告诉 automake 我们想要构建一个测试并运行它。该测试将构建到我们不想安装的可执行文件中。然后自动制作将运行该可执行文件。它将报告该可执行文件是否说测试通过或失败。

自动制作通过在生成文件中查找变量check_PROGRAMS来实现这一点。这些是它将编译的程序,但它不一定会运行它们。所以我们添加到/tests/Makefile.am

check_PROGRAMS = gtest
gtest_SOURCES = gtest.cpp
gtest_LDADD = libgtest.la
gtest_LDFLAGS = -pthread
gtest_CPPFLAGS = -I$(top_srcdir)/googletest/googletest/include -I$(top_srcdir)/googletest/googletest -pthread

gtest_SOURCES 查找/tests/gtest.cpp文件并对其进行编译。 gtest_LDADD链接,指向将编译到/tests 目录中的 libgtest.la。Google 希望我们使用 gtest_LDFLAGS 行来启用 pthreads。最后,我们需要包括找到标头"gtest/gtest.h"的位置,即gtest_CPPFLAGS行。Google 还希望我们包含/googletest/googletest位置,并包含

现状:Google 测试库libgtest.la将随make编译到目录/tests 中,但不会安装。二进制 gtest 只能用 make check 编译,但不会安装。

接下来,我们要告诉 automake 实际运行编译的二进制 gtest 并报告错误。这是通过在/tests/Makefile.am中添加一行来实现的:

TESTS = gtest

最终的/tests/Makefile.am 看起来像这样:

check_LTLIBRARIES = libgtest.la
libgtest_la_SOURCES = ../googletest/googletest/src/gtest-all.cc
libgtest_la_CPPFLAGS = -I$(top_srcdir)/googletest/googletest/include -I$(top_srcdir)/googletest/googletest -pthread
check_PROGRAMS = gtest demo
gtest_SOURCES = gtest.cpp ../src/fields.cpp
gtest_LDADD = libgtest.la
gtest_LDFLAGS = -pthread
gtest_CPPFLAGS = -I$(top_srcdir)/googletest/googletest/include -I$(top_srcdir)/src
demo_SOURCES = demo.cpp ../src/fields.cpp
demo_CPPFLAGS = -I$(top_srcdir)/src
TESTS = gtest

现在,从/ autoreconf -fiv(注意任何错误并希望修复它们)和make check,您应该得到一个运行的测试:

build(dev)$ make check
Making check in tests
/Applications/Xcode.app/Contents/Developer/usr/bin/make  gtest
make[2]: `gtest' is up to date.
/Applications/Xcode.app/Contents/Developer/usr/bin/make  check-TESTS
PASS: gtest
============================================================================
Testsuite summary for IonMotion 0.0.1
============================================================================
# TOTAL: 1
# PASS:  1
# SKIP:  0
# XFAIL: 0
# FAIL:  0
# XPASS: 0
# ERROR: 0
============================================================================

下面是单元测试项目(项目名称:测试项目)的示例 Makefile.am。这取决于GTEST和GMOCK:

Makefile.am

#######################################
# The list of executables we are building seperated by spaces
# the 'bin_' indicates that these build products will be installed
# in the $(bindir) directory. For example /usr/bin
#bin_PROGRAMS=exampleProgram
# Because a.out is only a sample program we don't want it to be installed.
# The 'noinst_' prefix indicates that the following targets are not to be
# installed.
noinst_PROGRAMS=utTestProject
#######################################
# Build information for each executable. The variable name is derived
# by use the name of the executable with each non alpha-numeric character is
# replaced by '_'. So a.out becomes a_out and the appropriate suffex added.
# '_SOURCES' for example.
# Sources for the a.out 
utTestProject_SOURCES= 
    utTestProject.cpp
# Library dependencies
utTestProject_LDADD = 
    $(top_srcdir)/../TestProject/build/${host}/libTestProject/.libs/libTestProject.a 
    ../$(PATH_TO_GTEST)/lib/libgtest.a 
    ../$(PATH_TO_GMOCK)/lib/libgmock.a 
# Compiler options for a.out
utTestProject_CPPFLAGS = 
    -std=c++11 
    -I../$(PATH_TO_GTEST)/include 
    -I../$(PATH_TO_GMOCK)/include 
    -I$(top_srcdir)/include 
    -I$(top_srcdir)/..
TESTS = utTestProject
TESTS_ENVIRONMENT = export UT_FOLDER_PATH=$(top_srcdir)/utTestProject; 
                    export GTEST_OUTPUT="xml";

编译测试:

# Useful vars
SourceVersionedArchiveFolderName="gtest-1.7.0"
#
# Make it
#
pushd .
cd ./${SourceVersionedArchiveFolderName}/make
make gtest.a
if [ $? != 0 ]; then
    echo "$0: Make failed"
    exit 1
fi
popd

值得注意的是,Googletest不再正式维护其Autotools集成:

在选择CMake之前,我们一直在提供手动维护的构建 Visual Studio、Xcode 和 Autotools 的项目/脚本。虽然我们 为了方便而继续提供它们,它们并不积极 再维护了。我们强烈建议您遵循 上述部分中的说明,用于将 Google 测试与您的 现有构建系统。

https://github.com/google/googletest/tree/master/googletest#legacy-build-scripts

现在建议使用 CMake 构建 Googletest。

使GoogleTest的源代码可用于主版本可以是 以几种不同的方式完成:

  • 手动下载GoogleTest源代码并将其放置在已知的 位置。这是最不灵活的方法,可以使其更加灵活 难以与持续集成系统等一起使用。
  • 嵌入 Google测试源代码作为主项目源代码中的直接副本 树。这通常是最简单的方法,但也是最难的方法 保持最新状态。某些组织可能不允许此方法。
  • 加 GoogleTest 作为 git 子模块或等效项。这可能并不总是 可能或适当。例如,Git 子模块有自己的 优点和缺点集。
  • 使用 CMake 将 GoogleTest 下载为 生成配置步骤的一部分。这只是多一点 复杂,但没有其他方法的局限性。

https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project