LINUX.ORG.RU

Как сподручнее организовать тесты для проектов на С/C++?

 


0

3

После JS, где берем mocha и фигачим тесты, на сшечке не совсем понятно, как добиться такой же простоты:

  • Написать функции с тестами не сложно, но потом вписывать каждую в main и следить что ничего не забыл как-то напряжно.
  • Иногда хочется напилить тесты на несколько файлов (как минимум для разных конфигов), но при этом иметь единый отчет.
  • Инструкции сборки надо как-то описывать, и не хотелось бы для каждого теста с этим уродоваться.
  • Coverage reports надо.

В общем, хотелось бы как в жыэс, тратить время именно на написание тестов, а не на то чтобы думать как их запустить.

Я видел что в Unity есть вспомогательный скрипт запуска на ruby, но как-то это все странно выглядит… В PlatformIO есть своя встроенная запускалка, которая на ряде проектов меня устраивает, но там многовато гвоздями приколочено и не всем понравится ставить pio только ради запуска тестов.

Подскажите, как сейчас для С/С++ принято тесты организовывать и запускать.

★★★★★

Последнее исправление: Vit (всего исправлений: 1)

как сейчас для С/С++ принято

ИМХО, это тот самый случай, когда упоминать и Си, и C++ вместе неуместно. Вы уточните, вам для чистого Си или же для C++. Поскольку даже в C++ есть несколько разного калибра варианты, сильно отличающиеся друг от друга (gTest, Boost.Test, Catch2/doctest как минимум). Ну и в C++ де-факто стандартом является CMake, поэтому если проект живет на CMake, то и тесты оформляются через CTest. В чистом Си, кмк, CMake еще не настолько стандарт.

eao197 ★★★★★
()

Правильно сказали выше - C/C++ семантически равно Java/JavaScript.

На счет Си, http://www.throwtheswitch.org/ , т.е. Unity (не 3d движок!) для юнит-тестов https://github.com/ThrowTheSwitch/Unity

Там нет никакого волшебства, похож на С++-сный Catch. Вот примеры использования из разных билд-систем: make http://www.throwtheswitch.org/build/make, CMake (с интеграцией CTest) http://www.throwtheswitch.org/build/cmake

Например, мы используем этот Юнити в embedded, немного добавив костылей под железо.

zendrz ★★
()

В общем, хотелось бы как в жыэс, тратить время именно на написание тестов, а не на то чтобы думать как их запустить.

Для этого тебе придется сначала все организовать. Самому. Например, у меня по make test из каталога с нужным тестом (или из родительского) запускаеются юниттесты на платах подключенных по usb-serial к моему компу. Тесты написаны с использованием unity, обвязка для запуска на плате - python. Тестов очень много, часть из них запускается на платах, часть - на PC. python + unity.

zendrz ★★
()
Ответ на: комментарий от eao197

Есть один проект LittlevGL, на чистом С, для которого надо организовать тесты в первую очередь.

Собственные поделки пишу на «Си с классами». Просто потому что удобны отдельные фичи вроде неймспейсов и нескольких вариантов сигнатур одной функции. Ну то есть компилятор плюсовый, но если скажу что пишу на плюсах, метана будет до небес :)

CTest посмотрю, спасибо. Я правильно понимаю, что он закрывает ВСЕ те вопросы которые я озвучил? Потому что уже пробовал юзать чистый Unity, накалякав кое-как Makefile, и меня организация билдов изрядно напрягла.

SCons есть смысл смотреть или CMake хватит за глаза?

Vit ★★★★★
() автор топика
Ответ на: комментарий от zendrz

Юнити это просто пачка удобных ассертов. А меня интересует именно запускалка, билды, и собирание репортов. Потому что взять чистый юнити и накорябать мейкфайл я уже пробовал, очень не понравилось.

Vit ★★★★★
() автор топика
Ответ на: комментарий от Vit

Есть один проект LittlevGL, на чистом С, для которого надо организовать тесты в первую очередь.

Про чистый Си не скажу, редко имею с ним дело.

CTest посмотрю, спасибо. Я правильно понимаю, что он закрывает ВСЕ те вопросы которые я озвучил?

ХЗ, у нас ситуация попроще, мы на счет code coverage не паримся. Собственно, в качестве основной системы сборки у нас свой велосипед, а CMake вынуждены использовать т.к. это типа де-факто стандарт и все такое, народу сильно проще пользоваться нашими разработками, когда там CMakeLists.txt есть.

Поэтому поддержку CMake для своих тестов мы когда-то скомуниздили откуда-то. Посмотреть что получилось можно здесь:

В качестве unit-test framework используется Catch2.

SCons есть смысл смотреть или CMake хватит за глаза?

Я вообще большой нелюбитель CMake, считаю что это недоразумение должно сдохнуть и чем раньше, тем лучше. Так что если у вас есть возможность с CMake не связываться и нет необходимости поддерживать CMake по каким-то причинам, то лучше это говно не трогать даже трехметровой палкой. ИМХО.

Но CMake гораздо больше распространен, так что найти что-то для CMake или получить какую-то помощь в Интернетах для CMake будет проще, чем для SCons-а.

eao197 ★★★★★
()
Ответ на: комментарий от Vit

Угу, понятно. Возможно тебе стоит прикрутить это к ctest\cmake , тогда ты получишь отчеты в каком нибудь junit формете автоматом. И распараллеливание запуска тестов. Ну и билды.

Я ctest не юзаю в этом проекте (о котором я говорил), т.к. там многое завязано на запуск не на хосте. У меня своё python фреймворк для фильтрации и сборки тестов (под разные архитектуры) и генерацию junit отчетов (import junit_xml в питоне и вперед :) )

В другом большом С++ проекте использовал gtest и прикручивал его к CTest (gtest_discover_tests()) - тоже получилось норм - отчеты, паралелльный запуск.

Как то так

zendrz ★★
()
Ответ на: комментарий от eao197

Я вообще большой нелюбитель CMake, считаю что это недоразумение должно сдохнуть и чем раньше, тем лучше. Так что если у вас есть возможность с CMake не связываться и нет необходимости поддерживать CMake по каким-то причинам, то лучше это говно не трогать даже трехметровой палкой. ИМХО.

Альтернативы-то какие проверенные, от которых душа возрадуется? Я бы и си с плюсами палкой еще десять лет не трогал, к десяти предыдущим. Но вот незадача, раст под эмбеды до юзабельного состояния не довели, а ждать больше совсем нельзя.

Vit ★★★★★
() автор топика
Ответ на: комментарий от zendrz

Тебе тоже спасибо за советы. А cmake сумеет помимо сишных тестов еще дополнительные внешние скрипты запустить? Я имею в виду не чисто технически, а чтобы это было удобно, как еще один тест добавить. Например, если надо дернуть какую-то программу и запарсить ее выхлоп.

Можешь Scons похвалить/поругать? Зачем на питоне свой фреймворк понадобился?

Vit ★★★★★
() автор топика
Последнее исправление: Vit (всего исправлений: 1)
Ответ на: комментарий от Vit

Альтернативы-то какие проверенные, от которых душа возрадуется?

Как я уже говорил, у нас свой лисапед, проверенный. Так что нам альтернативы CMake особо искать пока не нужно (пока еще C++20 не приняли с его модулями).

А вообще, в качестве альтернативы CMake сейчас можно рассматривать Meson, GN, Bazel, Buck.

Но мейстрим, все-таки, CMake.

eao197 ★★★★★
()
Ответ на: комментарий от Vit

угу, добавляешь любую команду\программу как

add_test(NAME MyCustomTest COMMAND runsomething...)

( https://cmake.org/cmake/help/latest/command/add_test.html )

По дефолту оно будет проверять возврат выхода != 0. Можно добавить указание парсинга stdout этой команды, типа

set_tests_properties(MyCustomTest PROPERTIES FAIL_REGULAR_EXPRESSION "[^a-z]Error;ERROR;Failed")

, как указано в доке.

Я сам не фанат и не гуру cmake\ctest - но оно работает и автоматизирует более менее :)

zendrz ★★
()
Ответ на: комментарий от Vit

Можешь Scons похвалить/поругать?

scons не сталкивался, сорр

Зачем на питоне свой фреймворк понадобился?

Мне надо запускать тесты на разных архитектурах (хост amd64, пара-тройка soc), на разных платах, с разными настройками этих плат. Питон фильтрует исходники по тестам, по тегам (в Си коде это все прописывается), делит все тесты на подмножества (например, все тесты не помещаются на память платы, или не на всём множестве плат надо это запускать и тп), собирает бинарники, заливает (работа с UART), читает и парсит выхлоп uart, конфигурит платы, ребутит, ждет таймауты и тп. Часть запускается на хосте, часть на qemu если реальное железо не надо. Потом делается отчет.

Т.к. unity тупой, как ты сам понял :) unity мы немного расширили ништяками вида define TEST_CASE(<name>, <tags>, <device_type>, <device_stage>) { ... } (немного похоже на gtest, не помню, или на catch, по синтаксиску), внутри которых пишутся уже юнитовские ассерты. Типа обертки над юнитовской RUN_TEST. Это парсится питоном, что бы сгенерировать команду билда (как я уже писал, выкинуть ненужное для данного профиля таргет\плата\настройки) бинарника. Сейчас где-то около 1.5k этих TEST_CASE в коде всего.

zendrz ★★
()
Ответ на: комментарий от slovazap

Это который Catch2?

Можешь кратко профит пояснить? Один кажется вижу - вроде не надо долбаться и перечислять все тесты в main, как у юнити (ну или писать внешний скрипт, который содержимое main будет генерить).

Есть какие-то еще особые плюшки?

Vit ★★★★★
() автор топика
Последнее исправление: Vit (всего исправлений: 1)
Ответ на: комментарий от Vit

Это который Catch2?

Можно и первый, он вроде немного легче. На самом деле я долгое время использовал самописный велосипед на 2 страницы кода, просто в catch это уже сделано и есть дополнительные фичи.

Можешь кратко профит пояснить? Один кажется вижу - вроде не надо долбаться и перечислять все тесты в main, как у юнити (ну или писать внешний скрипт, который содержимое main будет генерить).

Я не использовал юнити и не понимаю что значит «перечислять все тесты в main». Поинт был в том чтобы использовать C++ для тестов C кода, потому что это позволяет писать меньше бойлерплейта, и все адекватные фреймворки - плюсовые.

Примеры использования catch есть у них в документации - по мне ровно так должны выглядеть тесты, тут нет ничего лишнего и «долбаться» не с чем. В CMake тест описывается 2-3 строчками (add_executable, add_test, если нужно target_link_libraries).

slovazap ★★★★★
()

Тут много упоминается про CTest + Unity: потыкать пример можно тут. Написано кое-как, но работает.

Должно работать из корня через:

# cmake -DWITHTESTS=1 . ; make clean all tests

DarkAmateur ★★★★
()
Последнее исправление: DarkAmateur (всего исправлений: 1)
Ответ на: комментарий от slovazap

Единичный тест - это функция с пачкой ассертов внутри. Обычно тесты объединяют в группы, и репорты двухуровневые.

Когда копал юнити, там надо было тесты (функции) ручками вставить в тело main(), чтобы код вызывался. Это трындец. А в качестве костыля - скрипт на руби, который содержимое main генерит. Так себе решение, на любителя.

На Сatch надо просто обозначить main макросом. Не идеал, но вполне терпимо.

Спрошу народ, насколько им критично тесты не на чистом си. Теоретически им надо совместимость с зоопарком эмбеданутых компиляторов проверять, но на это обычного билда хватит. А тестов у них сейчас вообще нет :).

Vit ★★★★★
() автор топика
Ответ на: комментарий от Vit

На вкус и цвет. Чисто в теории, можно писать один-тест-на-файл и всё сведётся к файлу-шаблону.

DarkAmateur ★★★★
()
Последнее исправление: DarkAmateur (всего исправлений: 1)
Ответ на: комментарий от nikitos

А в чем у буста профит перед Catch2? Он же по идее толстый и в примере установки под венду нет. Catch на крайняк можно одним файлом скопировать.

У меня нет предрассудков насчет буста, просто интересно понять баланс между фичами/простотой и что будет удобнее для моего случая.

Vit ★★★★★
() автор топика
Ответ на: комментарий от Vit

Он же по идее толстый и в примере установки под венду нет.

Он модульный, можно собрать только то, что нужно. Насчет установки под винду - использую vcpkg, жить можно. Второй вариант вместо vcpkg - conan.io. Conan использует некоторый кровавый интерпрайз (pix4d), но мне пока не зашло.

nikitos ★★★
()
Последнее исправление: nikitos (всего исправлений: 2)

Имхо, cmake/ctest + gmock/gtest - самая мощная связка из того что имеется на рынке на данный момент.

Есть конечно catch, но он хорош для наколенных поделий скорее, т.к. супер быстрый старт. Boost::test можно использовать, когда не охота тащить ещё что-то, но использовать его чисто ради тестов, это такой себе мазохизм.

Поясню свою имху - тесты без мокапов это деньги на ветер, а движков для мокапа гораздо меньше, чем этих ваших тестовых, а что бы они ещё и стакались хорошо - так и вообще наверное больше нет.

pon4ik ★★★★★
()
Ответ на: комментарий от Vit

Так не набивай - подключи статическую либу и радуйся жизни. Напиши макрос для cmake и добавляй хоть каждый файл как тест, хоть через GLOB (хотя я бы такое на ревью не пущал).

pon4ik ★★★★★
()
Ответ на: комментарий от Vit

Это трейдофф. Либо явно набиваешь, какие тесты запускать, либо явно выключаешь ненужные/сломанные тесты. Какой вариант лучше — дело вкуса, но я лично предпочитаю говорить, что мне надо, а не наоборот. И еще, выключить тест в первом случае — закомментировать строчку. Во втором случае — магия, в каждом тестовом фреймворке своя. Меня бесит магия.

В CTest AFAIK по умолчанию включаются все тесты.

filosofia
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.