§ 2. Модульное тестирование
Модульное тестирование
01Частью любого проекта является набор тестов, которые запускаются после каждой сборки для проверки корректности кода. Как правило, запуск тестов выполняется автоматически после загрузки кода на центральный сервер, а результаты тестов отображаются на веб-интерфейсе сервера для ознакомления. Если тесты проходят успешно, код отправляется на проверку лидеру команды, и после этого сливается с основной веткой кода. Мы рассмотрим только первый шаг этого процесса — написание и запуск тестов.
Модульные тесты — это обычные программы на C++. Тест считается пройденным успешно, если функция main
возвращает 0. Тест пропускается, если main
возвращает 77 (это число досталось в наследство от старых систем). В любом другом случае тест завершается ошибкой.
Для создания тестов доступно большое количество библиотек, одной из которых является Google Test. Файлы с тестами пишутся в декларативном стиле с помощью макросов. Макросы построены на сравнении
#include <gtest/gtest.h> // заголовочный файл Google Test #include <algorithm> #include <cmath> TEST(Max, Compare) { EXPECT_EQ(10, std::max(10,1)); // ожидается 10 EXPECT_EQ(1, std::max(0,1)); // ожидается 1 EXPECT_EQ(1.0/0.0, std::max(1.0/0.0,-1.0/0.0)); // Inf EXPECT_TRUE(std::isnan(std::max(0.0/0.0,1.0/0.0))); // NaN EXPECT_TRUE(std::isnan(std::max(0.0/0.0,-1.0/0.0))); // NaN }
В тесте производится проверка функции std::max
. Функция main
в тестах отсутствует, поскольку предоставляется самой библиотекой gtest
.
Для того чтобы Meson создал модульный тест, необходимо обернуть команду executable
в команду test
и подключить библиотеку gtest
. Сами тесты, как правило, хранятся в отдельной директории, например, в src/test
(общая структура директорий описана в предыдущем задании). Поскольку тесты модульные, то каждый из них проверяет работу отдельной функции или класса и их название совпадает с проверяемой функцией или классом. Пример конфигурации приведен ниже.
gtest = dependency('gtest', main: true) test( 'myclass', executable( 'myclass_test', sources: ['myclass_test.cc'], include_directories: src, dependencies: [gtest] ) )
Флаг main
позволяет использовать или не использовать встроенную функцию main
. После этого все тесты можно запустить командой meson test
или ninja
test
.
Задания
02При выполнении заданий должны быть соблюдены следующие условия.
- Сборка кода должна быть сделана с помощью Meson.
- Тесты должны быть прописаны в Meson и запускаться с помощью
meson test
. - Все нижеперечисленные задания должны быть в одном проекте Meson.
- Структура проекта Meson должна быть похожа на следующую.
src └── myproject # название произвольное ├── vector.hh # основной код ├── vector_test.cc # код модульных тестов └── ...
Код тестов пишется в отдельном файле с суффиксом_test
. Все файлы находятся в директории с названием проекта. - Включение заголовочных файлов в код всегда делается с указанием имени проекта:
#include <myproject/vector.hh>
- Создайте простой тест для каждого из следующих методов и конструкторов класса
std::vector
:push_back
,pop_back
,erase
,begin
иend
,size
,vector(const vector&)
,vector(vector&&)
,vector& operator=(const vector&)
,vector& operator=(vector&&)
.
size
:TEST(vector, size) { std::vector<float> x; EXPECT_EQ(0u, x.size()); x.push_back(1); EXPECT_EQ(1u, x.size()); // ... }
- Создайте параметризованный тест для проверки метода
erase
. Параметром теста должна быть следующая структура.template <class T> struct Erase_params { // исходные элементы std::vector<T> elements; // начальный индекс, с которого начинается удаление элементов size_t start_index; // конечный индекс, на котором заканчивается удаление элементов size_t end_index; // элементы, которые останутся в векторе после удаления std::vector<T> result; };
- Создайте типизированный тест для проверки метода
push_back
. Параметром теста является тип элемента вектора. Используйте следующие типы в качестве параметра:float
,std::ofstream
,std::string
.
Ссылки
- Описание методов
std::vector
: ru.cppreference.com. - Реализация
std::vector
в стандартной библиотеке компилятора GCC:/usr/include/c++/10/bits/stl_vector.h
. Этот файл есть в любом дистрибутиве Linux, в котором установлен компилятор, но путь может отличаться.