Сборка и тестирование проекта при помощи CMake и CTest.

Думаю что большинство C++ разработчиков так или иначе сталкивались с CMake, в то же время что такое CTest и как с его помощью можно автоматизировать модельное тестирование знают далеко не все.
Для того, что бы показать как можно использовать CMake и CTest вместе, я в качестве примера создал маленькую библиотечку, состоящую из пары строк кода, которое умеет складывать и делить Кроме приложений CMake и CTest, понадобится какая-либо UnitTest библиотека (в данном примере я взял Boost.Test, хотя, можно взять и GoogleTest). Тут стоит обратить внимание на то, что CTest не является фрэймворком для написания тестов. CTest – это приложение для запуска тестов и, если это необходимо, отправки результатов в какое-либо из поддерживаемых хранилищ.
Структура директорий с тестовом приложении будет следующая:

.
./test
./test/main.cpp
./test/CMakeLists.txt
./include
./include/calc.h
./src
./src/CMakeLists.txt
./src/calc.cpp
./CMakeLists.txt

Таким образом, создаем один корневой CMakeLists и по одному CMakeLists файлу для описания сборки самой библиотеки и тестов.

cmake_minimum_required(VERSION 2.6)
project(AutoUnitTests)

SET (CMAKE_LIBRARY_OUTPUT_DIRECTORY
        ${PROJECT_BINARY_DIR}/bin
        CACHE PATH
        "Single Directory for all"
    )

SET (CMAKE_RUNTIME_OUTPUT_DIRECTORY
        ${PROJECT_BINARY_DIR}/bin
        CACHE PATH
        "Single Directory for all"
    )

SET (CMAKE_ARCHIVE_OUTPUT_DIRECTORY
        ${PROJECT_BINARY_DIR}/lib
        CACHE PATH
        "Single Directory for all"
    )

enable_testing()

find_package(Boost REQUIRED)

include_directories(include)

add_subdirectory( src build/src )
add_subdirectory( test build/test )

Первые три SET команды не обязательны, просто я не люблю когда в процессе сборки куча промежуточных файлов помещается в корневую директорию. А вот наличие команды enable_testing в корневом CMakeLists файле на оборот обязательно, если ее перенести в CMakeLists из директории test, то работать это не будет.
Следующим шагом будет создание CMakeLists файла в директории src, честно сказать, он из себя не малейшего интереса не представляет:

project(Calc)
set( Calc_source calc.cpp )
add_library( calc STATIC ${Calc_source} )

И последний файл, в директории test:

project(tests)

find_package (Boost COMPONENTS unit_test_framework REQUIRED)

set(test1_source main.cpp)
add_executable(test1 ${test1_source})
target_link_libraries(test1 ${Boost_LIBRARIES} calc)

add_test(NAME Test1 COMMAND test1)

Единственным отличаем от обычного CMakeLists файла будет команда add_test, в которую передается имя теста и то, какую команду необходимо выполнить для его запуска. Т.е. данная команда вполне может выглядеть и так:

add_test(testTkInter "/usr/bin/python" "-c" "import Tkinter")

Теперь, тесты на выполнение можно запускать при помощи команды make test и результат будет выглядеть следующим образом:

Running tests...
Test project /home/astavonin/Projects/AutoUnitTest
    Start 1: Test1
1/1 Test #1: Test1 ............................   Passed    0.03 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.56 sec

Если же добавить еще один тест, который должен провалиться, то результаты будут несколько иные:

Running tests...
Test project /home/astavonin/Projects/AutoUnitTest
    Start 1: Test1
1/2 Test #1: Test1 ............................   Passed    0.00 sec
    Start 2: Test2
2/2 Test #2: Test2 ............................***Failed    0.00 sec

50% tests passed, 1 tests failed out of 2

Total Test time (real) =   0.46 sec

The following tests FAILED:
      2 - Test2 (Failed)
Errors while running CTest

Консольный вывод тестовых приложений будет сохранен в директории ./Testing/Temporary.
Пример полностью можно скачать тут.

10 Comments Сборка и тестирование проекта при помощи CMake и CTest.

  1. me

    Только разбираюсь с CMake, потому спасибо за подсказку, буду пробовать на GTest. Шрифт вырвиглазен.

    Reply
    1. Alexander Stavonin

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

      Reply
  2. Alexandra

    А можно ли как-то сделать так, чтобы output из тестов (я использую gtest, выдается статистика по каждому тесту) не “проглатывался” при запуске make test?
    То есть, вместо

    Start 1: test1
    1/1 Test #1: test1 ……………………….***Exception: SegFault 0.21 sec

    0% tests passed, 1 tests failed out of 1

    было бы

    [==========] Running 14 tests from 4 test cases.
    [———-] Global test environment set-up.

    [ FAILED ] BucketsTestFixture.TestNonZeroCount (0 ms)
    [ RUN ] BucketsTestFixture.TestClear

    etc. ?

    Reply
  3. IFG

    >> Таки образом, создаем один к

    где-то в одних из первых абзацев. буква “м” пропущена?

    Reply
  4. Магомед Абдулвадудов

    Добрый день, Александр. Извините за детский вопрос. Но я часами мучаюсь, скачал ваш архив еще. А в какой директории я должен быть, что бы ввести эту команду “make test”?

    Reply
    1. Alexander Stavonin

      В корневой папке проекта. Но сначала надо выполнить просто `make`, который сгенерирует нужные файлы, и только потом `make test`. Ну и это для *NIX будет только работать, для Windows вместо Makefile придется писать bat-ник.

      Reply
  5. Vladimir Bashkirtsev

    Посту 7 лет, а актуальность на высоте! 🙂 Спасибо за архив с примером: хорошая затравка для нового проекта! 🙂

    Reply

Leave a Reply to Vladimir Bashkirtsev Cancel reply