Модульное тестирование кода C

806

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

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

  • 10
    Взгляните на cmocka.org
  • 0
    @zmo, есть ли другой веб-сайт SE, где вы можете задать тип вопросов, которые вы только что описали (общий вопрос, требующий библиотеки для выполнения задачи и т. д.)
Показать ещё 2 комментария
Теги:
unit-testing
testing
embedded

31 ответ

418
Лучший ответ

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

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 для г-на Андо на домашней странице.

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

Больше рамок:

CMocka

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

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

критерий

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

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

HWUT

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

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

CGreen

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

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

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

  • 0
    Изначально Check выглядит очень солидно. Мне нужно будет увидеть, как он выдерживает огонь реального использования ... но это определенно выглядит так, как будто оно отвечает всем требованиям.
  • 6
    Мы используем проверку для кода модульного тестирования в наших встроенных системах. По большей части проверка была хорошим выбором, но сейчас мы работаем на системах, работающих на uClinux, и поскольку проверка требует форка, она не работает на этих системах. : /
Показать ещё 11 комментариев
143

Лично мне нравится 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 cross, скомпилированного в Linux на архитектуре PowerPC. Это имеет смысл, потому что у вас есть полная оболочка и os для сбора ваших результатов. Для менее богатых сред (которые я классифицирую как угодно без полной ОС) вы должны просто создавать и запускать на хосте. Вы должны сделать это в любом случае, чтобы вы могли автоматически запускать тесты как часть сборки.

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

Michael Feathers имеет . В одной главе он описывает методы работы с кодом, отличным от OO, который я очень рекомендую.

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

Изменить. Я очень рекомендую.

  • 36
    Не C, но C ++.
  • 15
    Не покупай праг. прога книга. Он не содержит идей, которых нет в ответах на этот вопрос.
Показать ещё 3 комментария
118

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

  • 4
    У меня нет опыта работы со встроенными системами, поэтому я не могу это комментировать, но для небольших программ на Си (работа в школе, сценарии) это выглядит идеально. Отличная ссылка.
  • 26
    3 строки! Боже мой ^ _ ^
Показать ещё 3 комментария
38

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

http://cutest.sourceforge.net/

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

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

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

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

  • 1
    Я второй голос за CuTest. Я использовал его для разработки homebrew на Nintendo DS, и у меня не было никаких проблем с его настройкой или использованием.
  • 0
    Я третье это. Я скачал его, когда он был версии 1.4, и изменил его, чтобы сделать дамп в XML. Похоже, что есть версия 1.5, которую мне придется скачать и посмотреть.
Показать ещё 2 комментария
35

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

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

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

  • 1
    Unity в сочетании с автоматической генерацией макетов с использованием CMock довольно хорош.
  • 0
    Можете ли вы предложить хороший учебник для cmock?
Показать ещё 1 комментарий
31

Вы также можете взглянуть на 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();
}
  • 0
    Я вручную свернул свой собственный эквивалент libtap для своих собственных проектов, но теперь, когда я знаю, что это существует, мне больше не придется поддерживать мой. Здорово!
  • 0
    ok(TESTING==IsSimple(), "libtap is super easy to use")
26

Существует элегантная модульная платформа тестирования для 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 года.

  • 2
    Когда я смотрю на cmockery и cmocka, документация выглядит аналогично. Связаны ли эти проекты?
  • 4
    cmocka является преемником cmockery. Я разветвлял это, потому что это не поддерживается.
19

Я не прошел долгий процесс тестирования устаревшего приложения 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 требует немного большего понимания макетов для начала. Примеры помогут вам преодолеть это. Похоже, что он может справиться с более простой механикой.

  • 1
    +1 для cmockery
  • 7
    Вы должны взглянуть на cmocka.org, который является преемником cmockery!
Показать ещё 2 комментария
15

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

  • 0
    Я был так обеспокоен ошибкой в функции is_spare () ... но спасибо за ссылку! Я предполагаю, что TDD не ловит ВСЕ ошибки.
12

Мы писали 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

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

  • 0
    Upvote для красивой Colo (U) rs
12

Существует CUnit

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

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

  • 1
    Я попробовал embunit и был разочарован этим.
  • 1
    Например, посмотрите отчет об ошибке, который я отправил, а также другой отчет об ошибке, который не был обработан в течение 3 лет.
11

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

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

11

Я не использую фреймворк, я просто использую 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
  • 2
    Мы не используем автоинструментальные средства (хотя было бы неплохо отодвинуться в какой-то момент). Исторически я использовал основной метод для тестирования, и это неплохое решение.
7

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

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

6

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

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

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

6

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

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

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

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

  • 0
    Компилятор, в котором вы нуждаетесь, может быть c ++, но код, который вы тестируете, все еще может быть C. CxxTest - очень простая структура для использования
5

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

4

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

  • 0
    Вы должны взглянуть на cmocka.org, который является преемником Cmockery.
4
  • 0
    Вы должны взглянуть на cmocka.org, который является преемником cmockery.
4

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

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

  • 0
    Будет ли фреймворк Google работать с чистым C? Быстрый взгляд на страницу показывает, что это фреймворк C ++.
  • 4
    Google Test отлично, но это очень сильно фреймворк на C ++. Это довольно портативный и может быть использован для тестирования C, если вам нужно.
3

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

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

2

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

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

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

Примеры:

2

попробуйте lcut! - http://code.google.com/p/lcut

  • 3
    Некоторая документация будет полезна. История проекта и цели, список возможностей, преимущества перед существующими альтернативами и т. Д. Были бы полезны для людей, которые проверяют его впервые.
2

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

2

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

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

  • 6
    Вопрос о C, а не C ++
  • 3
    Нет, но C ++ может взаимодействовать с библиотеками C. Так что на самом деле может быть вполне нормально тестировать библиотеки C с использованием инфраструктуры модульного тестирования C ++. (Кстати, моя компания так поступает, и это намного проще, чем использовать фреймворки для модульного тестирования на Си).
Показать ещё 1 комментарий
1

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

1

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

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

1

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

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

0

Я просто написал Libcut из-за разочарования существующими библиотеками тестирования модулей C. Он имеет автоматическое строковое кодирование примитивов (нет необходимости в test_eq_int, test_eq_long, test_eq_short и т.д.), Только два разных набора для примитивов и строк) и состоит из одного файла заголовка. Вот краткий пример:

#include <libcut.h>

LIBCUT_TEST(test_abc) {
    LIBCUT_TEST_EQ(1, 1);
    LIBCUT_TEST_NE(1, 0);
    LIBCUT_TEST_STREQ("abc", "abc");
    LIBCUT_TEST_STRNE("abc", "def");
}

LIBCUT_MAIN(test_abc);

Он работает только с C11.

0

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

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

0

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню