Тестирование с использованием Google Test

Материал из Викиконспекты
Перейти к: навигация, поиск
НЕТ ВОЙНЕ

24 февраля 2022 года российское руководство во главе с Владимиром Путиным развязало агрессивную войну против Украины. В глазах всего мира это военное преступление совершено от лица всей страны, всех россиян.

Будучи гражданами Российской Федерации, мы против своей воли оказались ответственными за нарушение международного права, военное вторжение и массовую гибель людей. Чудовищность совершенного преступления не оставляет возможности промолчать или ограничиться пассивным несогласием.

Мы убеждены в абсолютной ценности человеческой жизни, в незыблемости прав и свобод личности. Режим Путина — угроза этим ценностям. Наша задача — обьединить все силы для сопротивления ей.

Эту войну начали не россияне, а обезумевший диктатор. И наш гражданский долг — сделать всё, чтобы её остановить.

Антивоенный комитет России

Распространяйте правду о текущих событиях, оберегайте от пропаганды своих друзей и близких. Изменение общественного восприятия войны - ключ к её завершению.
meduza.io, Популярная политика, Новая газета, zona.media, Майкл Наки.

Задача

Дан линейный порядок и два элемента. Необходимо перечислить элементы линейного порядка, которые находятся между данными, и протестировать решение на правильность и скорость.

Решение

Напишем функцию intersect, которая решает задачу поиска и перечисления с помощью эффективного алгоритма. Также напишем intersect_slow (для удобства — с той же сигнатурой), которая решает ту же задачу медленно, но достоверно.

Пишем два теста: на правильность и на скорость. В обоих генерируется вектор из случайных чисел, на котором запускаются обе функции. В первом случае результаты проверяются на равенство. Во втором подсчитываем время, затраченное обоими алгоритмами, и проверяем, быстрее ли наш эффективный алгоритм.

Реализация

Тестирование будет проводиться в main.cpp.

Подключение gtest к проекту

Добавим в CMakeLists.txt строчку

find_package(GTest)

и изменим строчку target_link_libraries, добавив туда ${GTEST_LIBRARY}, например:

target_link_libraries(${PROJECT\_NAME} ${GTEST_LIBRARY})

В main.cpp делаем

#include <gtest/gtest.h>.

Функция main()

Она будет выглядеть так:

int main(int argc, char ** argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

Первая строчка позволяет колдовать с разными флагами тестирования. RUN_ALL_TESTS() обязательно должен запускаться ровно один раз, а main должна возвращать его значение.

Собственно тест

Тесты выглядят так:

TEST(test_case_name, test_name)
{
    ... test body ...
}

test_case_name — имя тесткейза, test_name — имя теста внутри этого тесткейза. У разных тесткейзов могут быть тесты с одинаковыми именами, ибо полное имя теста составляется из обоих этих имён. Эти имена должны быть валидными плюсовыми идентификаторами. Утверждается, что они не должны содержать в себе подчёркиваний, но с ними всё отлично работает.

Собственно тестирование заключается в вызове, например, EXPECT_EQ(val1, val2), которое проверяет val1 и val2 на равенство. В случае, если они не равны, в выводе будет написано, что случился фейл в таком-то тесте и будут выведены значения val1 и val2. Также бывают EXPECT_LE (проверяет, что val1 <= val2), EXPECT_LT (val1 < val2) и т.д.

Кстати, тесты можно отключать: необходимо исправить test_name на DISABLED_test_name. Тогда этот тест не будет запускаться, а gtest сообщит о том, что имеются отключённые тесты.

Собственно реализация

https://github.com/katyatitkova/intersect_test

Кажущиеся проблемы нашего решения

Каждый тест запускается только один раз, нам этого недостаточно

Вспомним про флаги тестирования, посмотрим в справку по ним:

./intersect --help

(запускать в папке сборки). В частности, узнаем, что флаг --gtest_repeat=[COUNT] решает нашу проблему. Чтобы запуститься с этим флагом, набираем в консоли во всё той же папке сборки, например

./intersect --gtest_repeat=10

А мы вообще сможем повторно запуститься на тех же тестах, на которых завалились? Рандом всё-таки

Да, сгенерённые числа в каждом запуске будут одинаковыми. То есть, если мы вызовем ./intersect --gtest_repeat=10, каждый из этих 10 раз будет разным, но следующий запуск ./intersect --gtest_repeat=10 сгенерирует то же самое, что было в прошлый раз. (Подсказывают, что этот эффект достигается за счёт использования std::default_random_engine)