Google test framework c как пользоваться

Обновлено: 06.07.2024

1. Что такое gtest
gtest являетсяКросс-платформенная(Liunx, Mac OS X, Windows, Cygwin, Windows CE и Symbian) Среда модульного тестирования C ++, выпущенная Google. gtest создан для написания тестов C ++ на разных платформах. Он предоставляет множество утверждений, фатальных и нефатальных суждений, параметризации, «тестов на смерть» и т. Д.
Поняв, что такое gtest, давайте изучим некоторые правила использования gtest!
1. ТЕСТ-макрос серии gtest

Цель макроса TEST - создать простой тест, который определяет функцию теста, в которой вы можете использовать любой код C ++ и использовать для проверки предоставленные утверждения. В последующих статьях также будет упомянут макрос TEST_P, который здесь не будет представлен.

Во-вторых, утверждение серии gtest
gtest заявленные макросы можно разделить на две категории: одна - это макрос ASSERT, а другая - макрос EXPECT.
1. Серия ASSERT_: если не удается определить текущую точку, выйдите из текущей функции
2. Серия EXPECT_: если не удается определить текущую точку, продолжайте выполнение
Если вас не устраивает автоматический вывод информации об ошибке, вы также можете использовать оператор <<, чтобы распечатать журнал ошибок и вывести некоторую настроенную информацию.
ASSERT_ серия:

Далее, давайте проведем тест, реализуем функцию для нахождения абсолютного значения и используем ASSERT в макросе TEST для тестирования различных типов данных.

1>, правильный тест



3. Механизм событий серии gtest
Суть «событий» заключается в том, что инфраструктура предоставляет вам возможность выполнить собственный настраиваемый код при этих нескольких возможностях подготовки / очистки данных для тестовых случаев. gtest предоставляет множество механизмов событий. Подводя итог, можно выделить три типа событий gtest:
1. Событие TestSuite
Необходимо написать класс, наследовать test :: Test, а затем реализовать два статических метода: метод SetUpTestCase выполняется до первого TestCase; метод TearDownTestCase выполняется после последнего TestCase.
2. Событие TestCase
зависает до и после выполнения каждого случая, и необходимо реализовать метод SetUp и метод TearDown. Метод SetUp выполняется перед каждым TestCase, метод TearDown - после каждого TestCase.
3. Глобальные события
Чтобы реализовать глобальные события, вы должны написать класс, который наследует класс test :: Environment и реализует методы SetUp и TearDown внутри. Метод SetUp выполняется перед выполнением всех наблюдений, а метод TearDown - после выполнения всех наблюдений.
Например, глобальные события можно использовать следующими способами:
Помимо наследования класса test :: Environment, вам также нужно определить объект глобальной среды и добавить объект в тест глобальной среды.


4. Испытание на смерть серии gtest
«Смерть» здесь означает сбой программы. Обычно в процессе тестирования нам нужно учитывать различные входные данные, некоторые из которых могут непосредственно вызвать сбой программы. В настоящее время мы должны проверить, зависает ли программа, как и ожидалось, что также называется «тест на смерть». ".
Макрос, использованный в тесте на смерть:

Далее давайте сделаем еще один пример теста: как использовать тест на смерть, когда в программе возникают проблемы?


5. Простой пример gtest

В Visual Studio 2017 и более поздних версиях решение Google Test интегрировано в среду Visual Studio как компонент рабочей нагрузки Разработка классических приложений на C++. Чтобы проверить, установлен ли этот компонент на компьютере, откройте Visual Studio Installer и найдите Google Test в списке компонентов рабочей нагрузки.

Установка Google Test

Добавление проекта Google Test в Visual Studio 2019

  1. В обозревателе решений щелкните узел решения правой кнопкой мыши и выберите пункты Добавить > Новый проект.
  2. Задайте Язык как C++ и введите тест в поле поиска. Выберите в списке результатов Проект Google Test.
  3. Укажите имя тестового проекта и нажмите кнопку ОК.

Новый проект Google Test

Создание проекта Google Test в Visual Studio 2017

  1. В обозревателе решений щелкните узел решения правой кнопкой мыши и выберите пункты Добавить > Новый проект.
  2. В левой области выберите Visual C++ > Тест, а в центральной области — Проект Google Test.
  3. Укажите имя тестового проекта и нажмите кнопку ОК.

Новый проект Google Test

Настройка тестового проекта

В открывшемся диалоговом окне Конфигурация тестового проекта можно выбрать проект, который необходимо тестировать. При выборе проекта Visual Studio добавляет ссылку на него. Если проект не выбран, необходимо вручную добавить ссылки на проекты, которые следует тестировать. При выборе статического или динамического связывания с двоичными файлами Google Test следует учитывать те же факторы, что и в случае с любой другой программой C++. Дополнительные сведения см. в статье DLL в Visual C++.

Настройка проекта Google Test

Настройка дополнительных параметров

Чтобы настроить дополнительные параметры, в главном меню выберите Сервис > Параметры > Адаптер тестов для Google Test. Дополнительные сведения об этих параметрах см. в документации по Google Test.

Параметры проекта Google Test

Добавление директив include

Написание и запуск тестов

Все готово к написанию и выполнению тестов Google Test. Сведения о макросах тестов см. в учебнике по началу работы с Google Test. Сведения об обнаружении, выполнении и группировании тестов с помощью обозревателя тестов см. в статье Выполнение модульных тестов с помощью обозревателя тестов.


Когда вставал вопрос о тестировании кода, я не задумываясь использовал boost::test. Для расширения кругозора попробовал Google Test Framework. Помимо всяких имеющихся в нем плюшек, в отличии от boost::test проект бурно развивается. Хотел бы поделиться приобретенными знаниями. Всем кому интересно прошу

Ключевые понятия

Ключевым понятием в Google test framework является понятие утверждения (assert). Утверждение представляет собой выражение, результатом выполнения которого может быть успех (success), некритический отказ (nonfatal failure) и критический отказ (fatal failure). Критический отказ вызывает завершение выполнения теста, в остальных случаях тест продолжается. Сам тест представляет собой набор утверждений. Кроме того, тесты могут быть сгруппированы в наборы (test case). Если сложно настраиваемая группа объектов должна быть использована в различных тестах, можно использовать фиксации (fixture). Объединенные наборы тестов являются тестовой программой (test program).

Утверждения (assertion)

Утверждения, порождающие в случае их ложности критические отказы начинаются с ASSERT_, некритические — EXPECT_. Следует иметь ввиду, что в случае критического отказа выполняется немедленный возврат из функции, в которой встретилось вызвавшее отказ утверждение. Если за этим утверждением идет какой-то очищающий память код или какие-то другие завершающие процедуры, можете получить утечку памяти.

Имеются следующие утверждения (некритические начинаются не с ASSERT_, а с EXPECT_):

Простейшие логические

  • ASSERT_TRUE(condition);
  • ASSERT_FALSE(condition);

Сравнение

  • ASSERT_EQ(expected, actual); — =
  • ASSERT_NE(val1, val2); — !=
  • ASSERT_LT(val1, val2); — <
  • ASSERT_LE(val1, val2); — <=
  • ASSERT_GT(val1, val2); — >
  • ASSERT_GE(val1, val2); — >=

Сравнение строк

  • ASSERT_STREQ(expected_str, actual_str);
  • ASSERT_STRNE(str1, str2);
  • ASSERT_STRCASEEQ(expected_str, actual_str); — регистронезависимо
  • ASSERT_STRCASENE(str1, str2); — регистронезависимо

Проверка на исключения

  • ASSERT_THROW(statement, exception_type);
  • ASSERT_ANY_THROW(statement);
  • ASSERT_NO_THROW(statement);

Проверка предикатов

  • ASSERT_PREDN(pred, val1, val2, . valN); — N <= 5
  • ASSERT_PRED_FORMATN(pred_format, val1, val2, . valN); — работает аналогично предыдущей, но позволяет контролировать вывод

Сравнение чисел с плавающей точкой

  • ASSERT_FLOAT_EQ(expected, actual); — неточное сравнение float
  • ASSERT_DOUBLE_EQ(expected, actual); — неточное сравнение double
  • ASSERT_NEAR(val1, val2, abs_error); — разница между val1 и val2 не превышает погрешность abs_error

Вызов отказа или успеха

  • SUCCEED();
  • FAIL();
  • ADD_FAILURE();
  • ADD_FAILURE_AT(«file_path», line_number);

Можно написать собственную функцию, возвращающую AssertionResult

Можно контролировать типы данных с помощью функции ::testing::StaticAssertTypeEq<T1, T2>(). Компиляция пройдет с ошибкой в случае несовпадения типов T1 и T2.

В случае ложности утверждения, выдаются данные, использованные в утверждении. Кроме того, можно задать собственный комментарий:


Можно использовать расширенные наборы символов (wchar_t) как в комментариях, так и в утверждениях, касающихся строк. При этом выдача будет в UTF-8 кодировке.

Тесты (tests)

Для определения теста используется макрос TEST. Он определяет void функцию, в которой можно использовать утверждения. Как отмечалось ранее, критический отказ вызывает немедленный возврат из функции.


TEST принимает 2 параметра, уникально идентифицирующие тест, — название тестового набора и название теста. В рамках одного и того же тестового набора названия тестов не должны совпадать. Если название начинается с DISABLED_, это означает, что вы пометили тест (набор тестов) как временно не используемый.

Можно использовать утверждения не только в составе теста, но и вызывать их из любой функции. Имеется лишь одно ограничение — утверждения, порождающие критические отказы не могут быть вызваны из не void функций.

Фиксации (fixtures)

Случается, что объекты, участвующие в тестировании, сложно настраиваются для каждого теста. Можно задать процесс настройки один раз и исполнять его для каждого теста автоматически. В таких ситуациях используются фиксации.

Фиксация представляет собой класс, унаследованный от ::testing::Test, внутри которого объявлены все необходимые для тестирования объекты при этом в конструкторе либо функции SetUp() выполняется их настройка, а в функции TearDown() освобождение ресурсов. Сами тесты, в которых используются фиксации, должны быть объявлены с помощью макроса TEST_F, в качестве первого параметра которого должно быть указано не название набора тестов, а название фиксации.

Для каждого теста будет создана новая фиксация, настроена с помощью SetUp(), запущен тест, освобождены ресурсы с помощью TearDown() и удален объект фиксации. Таким образом каждый тест будет иметь свою копию фиксации «не испорченную» предыдущим тестом.

В некоторых случаях создание тестируемых объектов является очень дорогой операцией, а тесты не вносят никаких изменений в объекты. В таком случае можно не создавать фиксации заново для каждого теста, а использовать распределенную фиксацию с глобальным SetUp()и TearDown(). Фиксация автоматически становится распределенной, если в классе имеется хотя бы один статический член. Статические функции SetUpTestCase() и TearDownTestCase() будут вызываться для настройки объекта и освобождения ресурсов соответственно. Таким образом, набор тестов перед первым тестом вызовет SetUpTestCase(), а после последнего TearDownTestCase().

Если существует потребность в SetUp() и TearDown() для всей программы тестирования, а не только для набора теста, необходимо создать класс-наследник для ::testing::Environment, переопределить SetUp() и TearDown() и зарегистрировать его с помощью функции AddGlobalTestEnvironment.

Запуск тестов

Объявив все необходимые тесты, мы можем запустить их с помощью функции RUN_ALL_TESTS(). Функцию можно вызывать только один раз. Желательно, чтобы тестовая программа возвращала результат работы функции RUN_ALL_TESTS(), так как некоторые автоматические средства тестирования определяют результат выполнения тестовой программы по тому, что она возвращает.

Флаги

  • ./test --gtest_filter=TestCaseName.*-TestCaseName.SomeTest — запустить все тесты набора TestCaseName за исключением SomeTest
  • ./test --gtest_repeat=1000 --gtest_break_on_failure — запустить тестирующую программу 1000 раз и остановиться при первой неудаче
  • ./test --gtest_output=«xml:out.xml» — помимо выдачи в std::out будет создан out.xml — XML отчет с результатами выполнения тестовой программы
  • ./test --gtest_shuffle — запускать тесты в случайном порядке

Вместо заключения

В данном посте я кратко пробежался по основным функциям Google Test Framework. За более подробными сведениями следует обратиться к документации. Оттуда вы сможете почерпнуть информацию о ASSERT_DEATH используемом при падении программы, о ведении дополнительных журналов, о параметризованных тестах, настройке вывода, тестировании закрытых членов класса и многое другое.

UPD: По справедливому замечанию хабрапользователя nikel добавлена краткая инофрмация по использованию флагов.
UPD 2: Исправление разметки после изменений на Хабре (нативный тег source).

Как и любой уважающий себя язык программирования, C++ имеет фреймворки для написания модульных тестов, и даже не один, а очень много. В рамках этой заметки мы познакомимся с основами использования фреймворка Google Test. Это довольно легковесный, однако не в ущерб удобству и функциональности фреймворк, используемый в Chromium, LLVM, Protobuf, OpenCV, и других проектах. Кроме того, из IDE с ним умеет интегрироваться как минимум CLion.

Fun fact! Если вас интересует написание системных тестов, их намного удобнее писать на высокоуровневом языке вроде Python. В частности, для Python есть хороший тестовый фреймворк PyTest.

Если вы используете CMake, то тесты, использующие Google Test, добавляются в проект очень просто:

cmake_minimum_required ( VERSION 3.6 )

find_package ( GTest REQUIRED )
find_package ( Threads REQUIRED )

set ( CMAKE_CXX_STANDARD 11 )
set ( CMAKE_CXX_STANDARD_REQUIRED on )

add_executable (
TestSerialization ./TestSerialization.cpp
../src/User.cpp ../src/Date.cpp )

target_link_libraries (
TestSerialization $ Threads::Threads )

enable_testing ()
add_test ( TestSerialization "./TestSerialization" )

В качестве примера напишем тесты на сериализацию и десериализацию объектов Date и User из статьи Работа с JSON на C++ при помощи библиотеки RapidJSON:

Заметьте, что, хотя здесь эта возможность и не используется, в общем случае Google Test позволяет заводить глобальное состояние, используемое разными тестами. Это может быть целесообразным, как минимум, для ускорения тестов. В остальном же приведенный код крайне прост, поэтому разбирать его более подробно я не вижу смысла.

Пример вывода программы:

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (0 ms total)
[ PASSED ] 2 tests.

[ RUN ] TestSerialization.DateJson
../tests/TestSerialization.cpp:26: Failure
Expected: d1
Which is: Date(year = 1988, month = 8, day = 5)
To be equal to: d2
Which is: Date(year = 1988, month = 8, day = 6)
[ FAILED ] TestSerialization.DateJson (0 ms)

Кроме того, Google Test позволяет запускать заданное подмножество тестов:

./TestSerialization --gtest_repeat=10 --gtest_shuffle \
--gtest_random_seed=42

Если генерировать входные данные каждого теста псевдослучайным образом, получится что-то очень похожее на property-based тесты.

Наконец, Google Test умеет генерировать отчеты в формате XML, чтобы его было легче интегрировать с системами непрерывной интеграции (простите за тавтологию), интерактивными средами разработки, и так далее:

Резюмируя вышесказанное, Google Test делает всю рутину, позволяя вам сосредоточиться непосредственно на написании тестов. То есть, с ним вам придется писать намного меньше кода, чем без него.

Полную версию исходников к этому посту, как обычно, вы найдете на GitHub. Также вас может заинтересовать заметка Определение степени покрытия кода на C/C++ тестами, если вдруг вы ее пропустили.

А какими тестовыми фреймворками для C++ в это время суток пользуетесь вы?

Читайте также: