Как я могу использовать Google Test с моим проектом, который строит через autotools?

Кажется, что есть несколько ответов, которые относятся к типу, имеют смысл, но я не знаю, как это осуществить. И я не нашел исчерпывающего ответа.

Первая проблема

Google Test не должен быть установленной библиотекой, она должна быть построена вместе с проектом. (См. FAQ.) Насколько я могу судить, это означает, что библиотеки тестов Google зависят от моих модульных тестов и должны когда я запускаю "make check" в своем проекте в первый раз. Это должно создавать библиотеки Google Test в некоторых каталогах. Я не знаю, как это сделать. В нем упоминаются некоторые autotools script, которые устарели, и я не уверен, о чем они говорят, или как правильно указать мою сборку.

Вторая проблема

Предполагая, что сборка выполнена успешно, как мне написать тест, который использует мою локально скомпилированную версию Google Test для запуска тестов? Я предполагаю, что есть несколько команд Makefile.am, которые я помещал в каталог моих тестов. Но что это? И какой пример unit test, который использует Google Test?

Ответ 1

Я решил проблему к моему удовлетворению! Я буду двигаться полностью сейчас. Это в основном просит учебник. Есть много решений, которые должны быть приняты, надеюсь, логически, чтобы Google Test прекрасно подходил для автоинструментов. Поэтому я заранее прошу прощения за длинный ответ, но все детали должны быть там.

Первая проблема

Чтобы понять ответ, вопрос нужно немного перефразировать. Мы собираем Google Test как библиотеку, на которую будет ссылаться наш тестовый код. Библиотека не будет установлена. Вопрос, который мы хотим задать,

"Как настроить автоинструменты для компиляции Google Test в виде библиотеки, с которой наш тестовый код может ссылаться?"

Для этого нам нужно скачать Google Test и поместить его в наш проект. Я использую Github, поэтому я делаю это, добавляя подмодуль в корневой путь моего проекта:

$ git submodule add [email protected]: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 Test создавалась только после запуска 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

Это требует, чтобы subdir-объекты были включены в configure.ac. Это достигается путем добавления его в строку AM_INIT_AUTOMAKE. Мне также нужно включить make файл в AC_CONFIG_FILES. Мы также хотим использовать libtool, потому что мы компилируем библиотечные файлы (я объясню, почему и как это работает через мгновение). Чтобы использовать libtool, мы добавляем AM_PROG_AR, LT_INIT. Мы хотим, чтобы 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
                 ])

Мне также нужно включить подкаталог и строку, указывающую на макросы, в каталог макросов /m4 в моем /Makefile.am:

ACLOCAL_AMFLAGS = -I m4

SUBDIRS = src tests

Что это сделало? Libtool был включен с AM_PROG_AR и LT_INIT. Check_LTLIBRARIES означает, что мы будем использовать libtool для создания так называемой удобной библиотеки libgtest.la. С включенными объектами subdir он будет встроен в каталог /tests, но не установлен. Это означает, что всякий раз, когда мы хотим обновить наши тесты, нам не нужно перекомпилировать библиотеку Google Test libgtest.la. Это сэкономит время при тестировании и поможет нам выполнять итерации быстрее. Затем мы захотим скомпилировать наши модульные тесты позже по мере их обновления. Библиотека будет скомпилирована только после запуска make check, что make check сэкономить время, не компилируя ее, если все, что мы хотим сделать, - это make или make install.

Вторая проблема

Теперь необходимо уточнить вторую проблему: как вы (а) создаете тест (б), который связан с библиотеками Google Test и, таким образом, использует их? Вопросы как бы переплетены, поэтому мы отвечаем на них сразу.

Создание теста - это всего лишь вопрос помещения следующего кода в файл gtest.cpp расположенный по адресу /tests/gtest.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, что мы хотим построить тест и запустить его. Тест собирается встроить в исполняемый файл, который мы не хотим устанавливать. Затем automake собирается запустить этот исполняемый файл. Он сообщит, говорит ли этот исполняемый файл, что тесты пройдены или не пройдены.

Automake делает это, просматривая в make файле переменную 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 ссылается на libgtest.la, которая будет скомпилирована в каталог /tests. Google хочет, чтобы мы использовали строку gtest_LDFLAGS для включения pthreads. Наконец, нам нужно указать место, где будет найден заголовок "gtest/gtest.h", и это строка gtest_CPPFLAGS. Google также хочет, чтобы мы /googletest/googletest местоположение /googletest/googletest и /googletest/googletest

Положение вещей: библиотека Test Google libgtest.la откомпилироваться make в каталоге/тесты, но не может быть установлено. Двоичный 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
============================================================================

Ответ 2

Вот пример Makefile.am для проекта unit test (название проекта: TestProject). Это зависит от 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";

Компиляция gtest:

# 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

Ответ 3

Стоит отметить, что Googletest официально больше не поддерживает интеграцию с Autotools:

Прежде чем остановиться на CMake, мы предоставляли поддерживаемые вручную проекты/сценарии сборки для Visual Studio, Xcode и Autotools. Хотя мы продолжаем предоставлять их для удобства, они больше не поддерживаются. Мы настоятельно рекомендуем вам следовать инструкциям в приведенных выше разделах, чтобы интегрировать Google Test с существующей системой сборки.

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

Теперь рекомендуется создать Googletest с CMake.

Сделать исходный код GoogleTest доступным для основной сборки можно несколькими способами:

  • Загрузите исходный код GoogleTest вручную и разместите его в известном месте. Это наименее гибкий подход, который может усложнить использование с системами непрерывной интеграции и т.д.
  • Вставьте исходный код GoogleTest в виде прямой копии в основное дерево исходных текстов проекта. Часто это самый простой подход, но его также сложнее поддерживать в курсе. Некоторые организации могут не разрешить этот метод.
  • Добавьте GoogleTest как подмодуль git или эквивалентный. Это не всегда может быть возможным или уместным. Подмодули Git, например, имеют свой набор преимуществ и недостатков.
  • Используйте CMake для загрузки GoogleTest как часть шага настройки сборки. Это немного сложнее, но не имеет ограничений других методов.

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