# Базовая настройка тестирования. ## Используемые технологии - C++11 - CMake - GTest (Google test framework for C++) - Conan ## Структура проекта ``` - Project/ -- build/ --- --- bin/ ---- program -- include/ --- algo.h --- algo.c -- src/ --- main.c -- tests/ --- test.cpp - conanfile.txt - CMakeLists.txt ``` ## conanfile Для подключения тестового фреймворка используется система менеджмента артефактов Conan, которая позволяет осуществлять подключение заранее скомпилированных библиотек без необходимости их установки на ОС разработчика. Подключение осуществляется описанием корректных настроек в файле conanfile.txt: ``` [requires] gtest/cci.20210126 [generators] cmake ``` Таким образом, будет подключена последняя на момент написания данного документа сборка фреймворка тестирования. ## sources Исходные коды проекта разделены на две части: собственно исходники и включаемые файлы. Исходники - это код самой программы, использующей алгоритмы, описанные во включаемых заголовочных файлах. ### src/main.c В файле с программой подключается файл с тестируемым алгоритмом, который используется в коде программы: ```C++ #include #include "../include/algo.h" void swap(char* a, char* b); int main(int argc, const char** argv) { char a = -11; char b = 15; printf("a=%d; b=%d\n", a, b); swap(&a, &b); printf("a=%d; b=%d\n", a, b); return 0; } ``` Выводом данного кода будет: ``` user@debian: ./build/bin/prog a=-11; b=15 a=15; b=-11 ``` ### include/algo.h Подключаемый в код программ и тестов заголовочный файл должен содержать только одно объявление функций: ```C++ #ifndef algos #define algos void swap(char* a, char* b); #endif ``` ### include/algo.c файл с реализацией лаконичен: ```C++ #include "algos.h" void swap(char* a, char* b) { *a ^= *b; *b ^= *a; *a ^= *b; } ``` ## tests Тесты описываются в отдельном файле, из которого будет собран бинарный файл. Важно, что фреймворк работает только с С++11 или новее, поэтому использовать более старый стандарт не получится, а исходные файлы на С нужно включать в секции `extern "C"`. Каждый тест описывается в специальной макрофункции `TEST` в параметрах которой указывается детальное название теста. В данном примере будет использоваться только один ассерт - `EXPECT_EQ`, который проверяет значение переданной первым аргументом переменной на равенство второму аргументу ### tests/test.cpp ```C++ #include #include extern "C" { #include "../includes/algos.h" } TEST(HelloTest, WeTestHere) { char a = -11; char b = 15; swap(&a, &b); EXPECT_EQ(a, 15); EXPECT_EQ(b, -11); } TEST(AnotherTest, WeTestThere) { char a = -11; char b = -11; swap(&a, &b); EXPECT_EQ(a, -11); EXPECT_EQ(b, -11); } ``` ## CMake Сборщик CMake описывает правила, по которым будет сформировал Makefile для дальнейшей сборки утилитой GNU Automake или Ninja. В файл настроек необходимо включить строки подключения артефактов Conan, поскольку мы используем готовую сборку фреймворка тестирования, а не устанавливаем его на компьютер. Также в скрипте указывается два исполняемых файла - для сборки программы и тестов, соответственно. ``` cmake_minimum_required(VERSION 3.5) project(BasicC) enable_testing() # GoogleTest requires at least C++11 set(CMAKE_CXX_STANDARD 11) # conan dependencies include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) conan_basic_setup() # test executable add_executable(check tests/test.cpp include/algo.h include/algo.c) target_link_libraries(check ${CONAN_LIBS} gtest_main) # let make know we use tests include(GoogleTest) gtest_discover_tests(check) # application executable add_executable(prog src/main.c include/algo.h include/algo.c) ``` ## Запуск Запуск осуществляется из папки `build`, соответственно: - `conan install ..` (установить зависимости conan, описанные в файле папкой выше) - `cmake ..` (подготовить Makefile по правилам из файла папкой выше) - `make` (собрать проект) - `ctest` (запустить тесты) - `./bin/prog` (запустить программу) В результате запуска тестов получится следующий вывод: ``` Test project /home/user/Documents/book-c-basic/build Start 1: HelloTest.WeTestHere 1/2 Test #1: HelloTest.WeTestHere ............. Passed 0.01 sec Start 2: AnotherTest.WeTestThere 2/2 Test #2: AnotherTest.WeTestThere .......... Passed 0.00 sec 100% tests passed, 0 tests failed out of 2 Total Test time (real) = 0.01 sec ```