Полное руководство по CMake. Часть третья: Тестирование и пакетирование

в 16:28, , рубрики: C, c++, cmake, автоматизация рутины, для начинающих, компиляция, руководство для новичков, руководство для разработчика, руководство для чайников, системы сборки

Полное руководство по CMake. Часть третья: Тестирование и пакетирование - 1

Введение

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

Запуск CMake

Ниже приведены примеры использования языка CMake, по которым Вам следует попрактиковаться. Экспериментируйте с исходным кодом, меняя существующие команды и добавляя новые. Чтобы запустить данные примеры, установите CMake с официального сайта.

Пример тестирования

Как было сказано ранее, CMake поддерживает автоматическое тестирование программ. Данную возможность весьма легко использовать — достаточно лишь написать несколько команд в привычном CMakeLists.txt, а затем запустить тесты посредством ctest или make test. В Вашем распоряжении присутствует проверка вывода программ, динамический анализ памяти и многое другое.

Мы рассмотрим процесс тестирования программы на конкретном примере. Исходный файл Multiply.c содержит следующий код:

#include <stdio.h>
#include <stdlib.h>
#define ARG_COUNT 3

int main(const int argc, const char *argv[]) {
    if (argc != ARG_COUNT) {
        fprintf(stderr, "Error!n");
        return EXIT_FAILURE;
    }

    const int first = atoi(argv[1]);
    const int second = atoi(argv[2]);
    printf("The result is: %dn", first * second);

    return EXIT_SUCCESS;
}

Данный код выводит результат перемножения двух аргументов в консоль. Обратите внимание, что возможна также ситтуация возникновения ошибки, если реальное число аргументов не удоволетворяет ожидаемому: в таком случае в поток ошибок будет выведено Error!.

В том же каталоге находится файл CMakeLists.txt с описанием процесса сборки, содержащий приведённый ниже код:

cmake_minimum_required(VERSION 3.0)
project(MyProgram)
add_executable(Multiply Multiply.c)

set(MULTIPLY_TIMEOUT 1)

# Включить поддержку тестирования:
enable_testing()

# Добавить тесты:
add_test(FirstTest Multiply 15 207)
add_test(SecondTest Multiply -54 -785)
add_test(ThirdTest Multiply 85234)

# Установить поведение тестов:
set_tests_properties(FirstTest SecondTest ThirdTest
PROPERTIES TIMEOUT ${MULTIPLY_TIMEOUT})

set_tests_properties(FirstTest PROPERTIES
PASS_REGULAR_EXPRESSION "The result is: 3105"
FAIL_REGULAR_EXPRESSION "Error!")

set_tests_properties(SecondTest PROPERTIES
PASS_REGULAR_EXPRESSION "The result is: 42390"
FAIL_REGULAR_EXPRESSION "Error!")

set_tests_properties(ThirdTest PROPERTIES
PASS_REGULAR_EXPRESSION "Error!")

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

Следующие три команды add_test добавляют тесты к текущему проекту. Краткая форма данной команды первым аргументом принимает наименование теста, а последующие аргументы образуют команду оболочки для запуска теста.

Череда команд set_tests_properties устанавливает поведение отдельно взятых тестов. После списка наименований тестов следует ключевое слово PROPERTIES, сигнализирующее о начале списка свойств, имеющего вид <название свойства> <новое значение> и задаваемого для выбранных тестов. Полный список доступных свойств находится тут.

Для всех тестов задаётся максимальное время исполнения в одну секунду свойством TIMEOUT, а затем для последующих тестов устанавливается ожидаемый вывод свойствами PASS_REGULAR_EXPRESSION и FAIL_REGULAR_EXPRESSION (например, если происходит совпадение с регулярным выражением The result is: 3105, то выполнение теста FirstTest продолжается, а в случае совпадения с выражением Error! тест останавливается и считается неудавшимся).

Способы включения тестирования

Существует аналог команды enable_testing — это включение модуля CTest посредством команды include. В общем случае, включение модуля более универсально, однако между ними всё-же есть различие.

Команда enable_testing включает тестирование для текущего каталога, а также для всех последующих. Она должна находится в корневом CMakeLists.txt, так как CTest ожидает файл тестирования в корне сборки.

Включение модуля CTest конфигурирует проект для тестирования посредством CTest/CDash, а также автоматически определяет опцию BUILD_TESTING, принимающую истину при возможности проведения тестирования (по умолчанию — ON). Таким образом, при использовании данной команды, разумно описывать процесс тестирования подобным образом:

if(BUILD_TESTING)
    add_test(FirstTest Test 1)
    add_test(SecondTest Test 2)
    add_test(ThirdTest Test 3)
    # Следующие команды...
endif()

Исполнение тестирования

Чередой команд cmake . && make && ctest . запускаются на выполнение все три теста. Командой ctest -R <RegularExpression> исполняется набор тестов, удоволетворяющих заданному регулярному выражению. Например, команда ctest -R ThirdTest запускает лишь третьий тест.

Пример пакетирования

Для создания пакета исходных файлов, библиотек и исполняемых файлов Вам осталось лишь описать установку необходимых файлов с помощью команды install, а затем включить модуль CPack командой include:

# Установить исполняемый файл "Multiply" в директорию "bin":
install(TARGETS Multiply DESTINATION bin)

# Задать некоторые характеристики пакета:
set(CPACK_PACKAGE_NAME "Multiply")
set(CPACK_PACKAGE_VENDOR "MyCompany")
set(CPACK_PACKAGE_CONTACT "https://myprojectsite.org")
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "mycontacts@gmail.com")
set(CPACK_PACKAGE_DESCRIPTION "The most stupid program ever written")

# Задать используемый генератор пакетов:
set(CPACK_GENERATOR "DEB")

# Включить стандартный модуль "CPack":
include(CPack)

В данном случае, команда install уведомляет генератора пакетов о каталоге установки цели Multiply. Без написания команд установки генерация пакетов невозможна.

Далее перечисляются характеристики пакета заданием нескольких переменных. На самом деле, существует обилие подобных переменных, должным образом оформляющих пакеты. Большинство из них не обязательны, однако некоторые генераторы пакетов требуют их определения. Список переменных, общих для всех генераторов пакетов, доступен здесь.

Обязательно определение переменной CPACK_GENERATOR — она является списком генераторов пакетов, вызываемых утилитой cpack. В данном случае она принимает значение DEB, следовательно, в корневом каталоге обзорного приложения сгенерируется debian-пакет.

Наконец, подключается модуль CPack, конфигурирующий будущий пакет проекта, используя ранее определённые переменные и команду установки исполняемого файла, а также добавляющий две цели сборки — package и package_source (соответственно бинарная сборка и сборка исходных кодов).

Исполнение пакетирования

Чередой команд cmake . && make && make package запускается на выполнение выбранный генератор для создания бинарного пакета, а команды cmake . && make && make package_source генерируют пакет исходных кодов прямо в корневом каталоге.

Завершение

Статья вышла на свет с опозданием из-за неотложных обстоятельств, но я надеюсь, что Вы её оцените не меньше предыдущих. Разбор исходных файлов CMake популярного проекта выйдет до нового года в виде отдельной статьи (предлагайте варианты в комментариях). Удачи!

Автор: Gymmasssorla

Источник


* - обязательные к заполнению поля