Тестирование с использованием 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)