Вопрос

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

Есть ли способ сделать модульное тестирование простого кода C таким же простым, как модульное тестирование кода Java, например, с помощью Юнит?Мы будем очень признательны за любую информацию, которая будет применима конкретно к разработке встроенных систем (кросс-компиляция на платформу Arm-Linux).

Это было полезно?

Решение

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

AceUnit

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

GNU Автоюнит

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

cUnit

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

CUnit

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

КуТест

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

CppUnit

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

embUnit

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

МинЕдиница

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

CUnit для г-наАндо

Реализация CUnit, которая является довольно новой и, по-видимому, все еще находится на ранней стадии разработки.См. CUnit для г-наДомашняя страница Андо.

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

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

CMocka

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

Видеть домашняя страница CMocka.

Критерий

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

См. Домашняя страница критерия Чтобы получить больше информации.

HWUT

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

Видеть домашняя страница HWUT.

CЗеленый

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

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

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

Другие советы

Лично мне нравится Платформа тестирования Google.

Настоящая трудность при тестировании кода 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.

Редактировать:Eсть выходит новая книга от Pragmatic Programmers это специально касается кода C для модульного тестирования, который я очень рекомендую.

Минединица — невероятно простая среда модульного тестирования.Я использую его для модульного тестирования кода микроконтроллера c для avr.

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

http://cutest.sourceforge.net/

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

  • Файл заголовка, включенный везде, где вы называете самые симпатичные процедуры
  • Один дополнительный файл 'c', который должен быть скомпилирован/связан с изображением
  • Некоторый простой код, добавленный в Main для настройки и вызов модульных тестов - у меня просто есть это в специальной функции Main (), которая собирается скомпилируется, если unittest определяется во время сборки.

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

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

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

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

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

Вы также можете взглянуть на 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();
}

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

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

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: Модульное тестирование с использованием макетов объектов в C

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

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

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

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

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

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

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

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

Обновление 1

Еще один фреймворк, который я изучаю, — Cmockery.

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

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

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

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

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

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

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

Есть CUnit

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

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

Я не использую фреймворк, я просто использую autotools, чтобы «проверить» целевую поддержку.Реализуйте «основной» и используйте утверждения.

Мой тестовый каталог 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

Мы написали ИЗМЕНЯТЬ (размещается на 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

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

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

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

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

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

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

Я предпочитаю CxxTest, потому что у него есть сценарий Perl/Python для создания средства запуска тестов.После небольшого уклона в настройке (еще меньшего, поскольку вам не нужно писать программу запуска тестов), его довольно легко использовать (включает примеры и полезную документацию).Большая часть работы заключалась в настройке «аппаратного обеспечения», к которому обращается код, чтобы я мог эффективно тестировать модуль/модуль.После этого легко добавлять новые модульные тесты.

Как упоминалось ранее, это среда модульного тестирования C/C++.Итак, вам понадобится компилятор C++.

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

кроме моей очевидной предвзятости

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

это хороший простой способ модульного тестирования кода C.имитирует xUnit

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

издевательство над http://code.google.com/p/cmockery/

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

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

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

Сначала посмотрите здесь: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C

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

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

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

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

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

Проверка работоспособности API — тестовая среда для библиотек C/C++:

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

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

Примеры:

Один из методов, который можно использовать, — это разработка кода модульного теста с использованием платформы C++ xUnit (и компилятора C++), сохраняя при этом исходный код целевой системы в виде модулей C.

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top