Единичное тестирование C Код

Этим летом я работал над встроенной системой, написанной прямо на C. Это был существующий проект, который перешла к компании, в которой я работаю. Я довольно привык к написанию модульных тестов в Java с использованием JUnit, но не знал, как лучше написать модульные тесты для существующего кода (который требует рефакторинга), а также для добавления нового кода в систему.

Существуют ли какие-либо проекты, которые делают модульное тестирование простым C-кодом столь же простым, как модульное тестирование Java-кода с помощью JUnit? Будем весьма благодарны за любые идеи, которые будут относиться конкретно к разработке встраиваемых систем (кросс-компиляция для платформы arm-linux).

Ответ 1

Одним из основ модульного тестирования в C является Check; Список платформ модульного тестирования в C можно найти здесь here и воспроизвести ниже. В зависимости от того, сколько стандартных библиотечных функций имеет ваша среда выполнения, вы можете или не сможете использовать одну из них.

AceUnit

AceUnit (Advanced C и Embedded Unit) позиционирует себя как удобную среду модульного тестирования кода C. Он пытается имитировать JUnit 4.x и включает в себя возможности, подобные отражению. AceUnit может использоваться в средах с ограниченными ресурсами, например, разработка встроенного программного обеспечения, и, что важно, он отлично работает в средах, где вы не можете включить один стандартный файл заголовка и не можете вызвать одну стандартную функцию C из библиотек ANSI/ISO C. У этого также есть порт Windows. Он не использует вилки для захвата сигналов, хотя авторы выразили заинтересованность в добавлении такой функции. Посетите домашнюю страницу AceUnit.

GNU Autounit

Во многом по той же схеме, что и Check, включая разветвление для запуска модульных тестов в отдельном адресном пространстве (фактически, первоначальный автор Check заимствовал эту идею из GNU Autounit). GNU Autounit широко использует GLib, а это означает, что для линковки и тому подобного необходимы специальные опции, но это может не быть для вас большой проблемой, особенно если вы уже используете GTK или GLib. Посетите домашнюю страницу GNU Autounit.

Куните

Также использует GLib, но не разветвляется для защиты адресного пространства модульных тестов.

Куните

Стандартный C, с планами по реализации Win32 GUI. В настоящее время не разветвляется или иным образом не защищает адресное пространство модульных тестов. В начале разработки. Смотрите домашнюю страницу CUnit.

симпатичный

Простая структура с одним .c и одним .h файлом, который вы перетаскиваете в дерево исходных текстов. Посетите домашнюю страницу CuTest.

CppUnit

Основная система модульного тестирования для C++; Вы также можете использовать его для тестирования кода C. Он стабилен, активно развивается и имеет графический интерфейс. Основные причины не использовать CppUnit для C: во-первых, он довольно большой, а во-вторых, вы должны написать свои тесты в C++, что означает, что вам нужен компилятор C++. Если это не похоже на проблемы, это, безусловно, стоит рассмотреть, наряду с другими C++ модульными системами тестирования. Посетите домашнюю страницу CppUnit.

embUnit

embUnit (Embedded Unit) - это еще одна инфраструктура модульного тестирования для встроенных систем. Этот, кажется, заменен AceUnit. Домашняя страница встраиваемого модуля.

MinUnit

Минимальный набор макросов и все! Суть в том, чтобы показать, как легко выполнить модульное тестирование вашего кода. Посетите домашнюю страницу MinUnit.

Блок для мистера Андо

Реализация CUnit, которая является довольно новой и, видимо, все еще находится на ранней стадии разработки. См. домашнюю страницу CUnit for Mr. Ando.

Этот список последний раз обновлялся в марте 2008 года.

Больше фреймворков:

CMocka

CMocka - это тестовая среда для C с поддержкой фиктивных объектов. Он прост в использовании и настройке.

Смотрите домашнюю страницу CMocka.

Критерий

Criterion - это кроссплатформенная инфраструктура модульного тестирования C, поддерживающая автоматическую регистрацию тестов, параметризованные тесты, теории и способная выводить данные в несколько форматов, включая TAP и JUnit XML. Каждый тест выполняется в своем собственном процессе, поэтому о сигналах и сбоях можно сообщать или тестировать при необходимости.

См. домашнюю страницу критерия для получения дополнительной информации.

HWUT

HWUT - это общий инструмент модульного тестирования с отличной поддержкой C. Он может помочь создавать Make файлы, генерировать массивные тестовые примеры, закодированные в минимальных "таблицах итераций", проходить по конечным автоматам, генерировать C-заглушки и многое другое. Общий подход довольно уникален: вердикты основаны на "хороший стандартный вывод/плохой стандартный вывод". Функция сравнения, однако, является гибкой. Таким образом, любой тип сценария может быть использован для проверки. Это может быть применено к любому языку, который может производить стандартный вывод.

Смотрите домашнюю страницу HWUT.

CGreen

Современная, переносимая, мультиязычная модульная система тестирования и моделирования для C и C++. Он предлагает дополнительную нотацию BDD, библиотеку-макет, возможность запускать ее в одном процессе (для облегчения отладки). Доступен тестовый прогон, который автоматически обнаруживает функции теста. Но вы можете создавать свои собственные программно.

Все эти функции (и многое другое) описаны в руководстве CGreen.

Википедия дает подробный список платформ модульного тестирования на C в разделе Список платформ модульного тестирования: C

Ответ 2

Лично мне нравится Google Test Framework.

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

Об этом говорят люди, когда говорят о "швах". В C ваш единственный вариант - использовать препроцессор или компоновщик для макетирования ваших зависимостей.

Типичный набор тестов в одном из моих проектов на C может выглядеть следующим образом:

#include "myimplementationfile.c"
#include <gtest/gtest.h>

// Mock out external dependency on mylogger.o
void Logger_log(...){}

TEST(FactorialTest, Zero) {
    EXPECT_EQ(1, Factorial(0));
}

Обратите внимание, что вы на самом деле используете файл C, а не файл заголовка. Это дает преимущество доступа ко всем статическим элементам данных. Здесь я делаю макет своего логгера (который может быть в logger.o и дает пустую реализацию. Это означает, что тестовый файл компилируется и связывается независимо от остальной части кода и выполняется изолированно.

Что касается кросс-компиляции кода, чтобы это работало, вам нужны хорошие средства на цели. Я сделал это с помощью googletest, скомпилированного для Linux на архитектуре PowerPC. Это имеет смысл, потому что у вас есть полная оболочка и ОС для сбора ваших результатов. Для менее богатых сред (которые я классифицирую как что-либо без полноценной ОС) вы должны просто собрать и запустить на хосте. В любом случае вы должны сделать это, чтобы вы могли запускать тесты автоматически как часть сборки.

Я считаю, что тестирование кода C++, как правило, намного проще из-за того, что ОО-код, как правило, гораздо менее связан, чем процедурный (конечно, это сильно зависит от стиля кодирования). Также в C++ вы можете использовать приемы, такие как внедрение зависимостей и переопределение методов, чтобы получить швы в коде, который инкапсулирован в противном случае.

У Майкла Фезерса есть превосходная книга о тестировании устаревшего кода. В одной главе он описывает методы работы с не-OO-кодом, которые я настоятельно рекомендую.

Изменить: я написал сообщение в блоге о процедурном коде модульного тестирования, источник доступен на GitHub.

Редактировать. Существует новая книга , разработанная Pragmatic Programmers, специально посвященная модульному тестированию кода C, который я настоятельно рекомендую.

Ответ 3

Minunit - невероятно простая модульная система тестирования. Я использую его для unit test c кода микроконтроллера для avr.

Ответ 4

В настоящее время я использую каркас CuTest unit test:

http://cutest.sourceforge.net/

Он идеален для встроенных систем, поскольку он очень легкий и простой. У меня не было проблем с его работой на целевой платформе, а также на рабочем столе. В дополнение к написанию модульных тестов требуется все:

  • заголовочный файл включен везде вы вызываете подпрограммы CuTest
  • один дополнительный файл 'C', который должен быть скомпилировано/связано с изображением
  • некоторый простой код, добавленный к основному настроить и называть модульные тесты - I просто используйте это в специальном главном() функция, которая компилируется, если UNITTEST определяется во время построить.

Система должна поддерживать кучу и некоторые функции stdio (которые не все встроенные системы). Но код достаточно прост, что вы, вероятно, могли бы работать в альтернативах этим требованиям, если ваша платформа их не имеет.

С некоторым разумным использованием блоков extern "C" {} он также поддерживает тестирование С++ просто отлично.

Ответ 5

Я говорю почти так же, как ratkok, но если у вас есть встроенный твист для модульных тестов, тогда...

Unity - Очень рекомендуемая основа для модульного тестирования кода C.

Примеры в книге, которые упоминаются в этом потоке TDD для встроенного C, написаны с использованием Unity (и CppUTest).

Ответ 6

Вы также можете взглянуть на libtap, структуру тестирования C, которая выводит протокол Test Anything Protocol (TAP) и, таким образом, хорошо интегрируется с различными инструментами для этой технологии. Он в основном используется в динамическом языковом мире, но он прост в использовании и становится очень популярным.

Пример:

#include <tap.h>

int main () {
    plan(5);

    ok(3 == 3);
    is("fnord", "eek", "two different strings not that way?");
    ok(3 <= 8732, "%d <= %d", 3, 8732);
    like("fnord", "f(yes|no)r*[a-f]$");
    cmp_ok(3, ">=", 10);

    done_testing();
}

Ответ 7

Существует элегантная модульная платформа тестирования для C с поддержкой макетных объектов под названием cmocka. Он требует только стандартную библиотеку C, работает на ряде вычислительных платформ (включая встроенные) и с разными компиляторами.

Он также поддерживает различные форматы вывода сообщений, такие как Subunit, Test Anything Protocol и jUnit XML-отчеты.

cmocka был создан для работы на встроенных платформах, а также имеет поддержку Windows.

Простой тест выглядит следующим образом:

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
    (void) state; /* unused */
}

int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(null_test_success),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}

API полностью документирован, и несколько примеров являются частью исходного кода.

Чтобы начать работу с cmocka, вы должны прочитать статью на LWN.net: Модульное тестирование с помощью mock-объектов в C

cmocka 1.0 был выпущен в феврале 2015 года.

Ответ 8

Я не прошел долгий процесс тестирования устаревшего приложения C, прежде чем начал искать способ издеваться над функциями. Мне нужно было издеваться над тем, чтобы изолировать файл C, который я хочу проверить у других. Я дал попытку, и я думаю, что смогу принять ее.

Cmock сканирует файлы заголовков и генерирует макетные функции на основе найденных им прототипов. Mocks позволит вам протестировать файл C в идеальной изоляции. Все, что вам нужно сделать, это связать ваш тестовый файл с mocks вместо ваших реальных объектных файлов.

Другим преимуществом cmock является то, что он будет проверять параметры, переданные на издеваемые функции, и он позволит вам указать, какое возвращаемое значение должны предоставить mocks. Это очень полезно для тестирования различных потоков выполнения в ваших функциях.

Тесты состоят из типичных функций testA(), testB(), в которых вы строите ожидания, вызываете функции для проверки и проверки утверждений.

Последний шаг - создать бегун для ваших тестов с единством. Cmock привязан к рамке проверки единства. Unity так же легко узнать, как и любая другая инфраструктура unit test.

Хорошо стоит попробовать и довольно легко понять:

http://sourceforge.net/apps/trac/cmock/wiki

Обновление 1

Другая структура, которую я изучаю, - это Cmockery.

http://code.google.com/p/cmockery/

Это чистая C-платформа, поддерживающая модульное тестирование и издевательство. Он не имеет никакого отношения к ruby ​​(вопреки Cmock), и он очень мало зависит от внешних libs.

Для настройки mocks требуется немного более ручная работа, потому что она не генерирует код. Это не представляет большой работы для существующего проекта, так как прототипы не будут сильно меняться: если у вас есть свои макеты, вам не нужно будет их менять некоторое время (это мой случай). Дополнительная набивка обеспечивает полный контроль над mock. Если вам что-то не нравится, вы просто меняете свой макет.

Нет необходимости в специальном тестировщике. Вам нужно только создать массив тестов и передать его функции run_tests. Здесь немного больше ручной работы, но мне определенно нравится идея автономной автономной структуры.

Плюс он содержит некоторые изящные трюки, которые я не знал.

В целом Cmockery требует немного большего понимания макетов для начала. Примеры помогут вам преодолеть это. Похоже, что он может справиться с более простой механикой.

Ответ 9

Как новичок C, я нашел слайды под названием Test driven development в C очень полезными. В принципе, он использует стандартный assert() вместе с && для доставки сообщения без каких-либо внешних зависимостей. Если кто-то используется для полной проверки стека, это, вероятно, не будет делать:)

Ответ 10

Мы писали CHEAT (размещались на GitHub) для удобства использования и переносимости.

Он не имеет зависимостей и не требует установки или конфигурации. Требуется только файл заголовка и тестовый пример.

#include <cheat.h>

CHEAT_TEST(mathematics_still_work,
    cheat_assert(2 + 2 == 4);
    cheat_assert_not(2 + 2 == 5);
)

Тесты компилируются в исполняемый файл, который заботится о запуске тестов и сообщает об их результатах.

$ gcc -I . tests.c
$ ./a.out
..
---
2 successful of 2 run
SUCCESS

У него тоже красивые цвета.

Ответ 11

Существует CUnit

И Встроенный модуль - это модульная система тестирования для системы Embedded C. Его дизайн был скопирован с JUnit и CUnit и более, а затем немного адаптирован для Embedded C System. Embedded Unit не требует std C libs. Все объекты выделены для константной области.

И Tessy автоматизирует модульное тестирование встроенного программного обеспечения.

Ответ 12

Я не использую фреймворк, я просто использую autotools "check" target support. Внесите "основные" и используйте assert (s).

Мой тестовый файл Makefile.am(s) выглядит так:

check_PROGRAMS = test_oe_amqp

test_oe_amqp_SOURCES = test_oe_amqp.c
test_oe_amqp_LDADD = -L$(top_builddir)/components/common -loecommon
test_oe_amqp_CFLAGS = -I$(top_srcdir)/components/common -static

TESTS = test_oe_amqp

Ответ 13

Книга Майкла Пера "Эффективно работающая с устаревшим кодом" представляет множество методов, специфичных для модульного тестирования во время разработки C.

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

Ответ 14

CppUTest - Очень рекомендуемая структура для модульного тестирования кода C.

Примеры в книге, которые упоминаются в этом потоке TDD для встроенного C, записываются с использованием CppUTest.

Ответ 15

Я использую CxxTest для встроенной среды c/С++ (прежде всего С++).

Я предпочитаю CxxTest, потому что у него есть perl/python script, чтобы создать тестовый бегун. После небольшого наклона, чтобы настроить его (поменьше, так как вам не нужно писать тест-бегун), он довольно прост в использовании (включает образцы и полезную документацию). Большая часть работы заключалась в настройке "аппаратного обеспечения" доступа к коду, чтобы я мог эффективно тестировать модуль/модуль. После этого легко добавить новые unit test случаи.

Как уже упоминалось ранее, это C/С++ unit test. Поэтому вам понадобится компилятор С++.

Руководство пользователя CxxTest CxxTest Wiki

Ответ 16

кроме моего очевидного смещения

http://code.google.com/p/seatest/

- хороший простой способ для кода unit test C. имитирует xUnit

Ответ 17

Прочитав Minunit, я подумал, что лучший способ - это основа теста в макросах assert, который я использую много, как технику защитной программы. Поэтому я использовал ту же идею, что и Minunit, смешанный со стандартным утверждением. Вы можете увидеть мою фреймворк (хорошее имя может быть NoMinunit) в k0ga blog

Ответ 18

У Google отличная система тестирования. https://github.com/google/googletest/blob/master/googletest/docs/primer.md

И да, насколько я вижу, он будет работать с простым C, то есть не требует функций C++ (может потребоваться компилятор C++, не уверен).

Ответ 20

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

Ответ 21

Во-первых, смотрите здесь: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C

В моей компании есть библиотека C, которую используют наши клиенты. Мы используем CxxTest (библиотека С++ unit test) для проверки кода. CppUnit также будет работать. Если вы застряли на C, я бы рекомендовал RCUNIT (но CUnit тоже хорош).

Ответ 22

Если вы знакомы с JUnit, я рекомендую CppUnit. http://cppunit.sourceforge.net/cppunit-wiki

Это предполагает, что у вас есть компилятор С++ для выполнения модульных тестов. если нет, то я должен согласиться с Адамом Розенфилдом, что проверка - это то, что вы хотите.

Ответ 23

Я использовал RCUNIT для выполнения некоторых модульных тестов для встроенного кода на ПК перед тестированием на цель. Хорошая абстракция аппаратного интерфейса важна, чтобы другие конечные элементы и регистры с отображением памяти собирались убить вас.

Ответ 25

API Sanity Checker - тестовая среда для библиотек C/С++:

Автоматический генератор базовых модульных тестов для общей библиотеки C/С++. Он способен генерировать разумные (в большинстве, но, к сожалению, не во всех случаях) входные данные для параметров, и составлять простые ( "здравомыслящие" или "мелкие" -качества) тестовые примеры для каждой функции в API посредством анализа объявлений в заголовке файлы.

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

Примеры:

Ответ 26

Один из способов использования - разработать код unit test с помощью С++ xUnit framework (и компилятора С++), сохраняя при этом источник целевой системы как C-модули.

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

Ответ 27

LibU (http://koanlogic.com/libu) имеет модуль unit test, который допускает явные зависимости набора тестов/случаев, тестовую изоляцию, параллельное выполнение и настраиваемый форматировщик отчетов (форматы по умолчанию - xml и txt).

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

Ответ 28

Я удивлен, что никто не упомянул Cutter (http://cutter.sourceforge.net/) Вы можете протестировать C и С++, он легко интегрируется с autotools и имеет действительно хороший учебник.

Ответ 29

Если вы ориентируетесь на платформы Win32 или режим ядра NT, вы должны взглянуть на cfix.

Ответ 30

Если вы все еще находитесь в поиске тестовых фреймворков, CUnitWin32 является одним для платформы Win32/NT.

Это решает одну фундаментальную проблему, с которой я столкнулся с другими платформами тестирования. А именно глобальные/статические переменные находятся в детерминированном состоянии, потому что каждый тест выполняется как отдельный процесс.