модульное тестирование кода c

<p>этим летом я работал над встроенной системой, написанной прямо на c. это был существующий проект, который перешла к компании, в которой я работаю. я привык к написанию модульных тестов в java с использованием junit, но не знал, как лучше написать модульные тесты для существующего кода (который требует рефакторинга), а также для добавления нового кода в систему. ,.</p><p>есть ли способ сделать модульное тестирование простым c-кодом таким же простым, как модульное тестирование java кода, например, <em>junit</em>? будем весьма благодарны за любые идеи, которые будут относиться конкретно к разработке встраиваемых систем (кросс-компиляция для платформы arm-linux).</p>

<p>основой для модульного тестирования в c является <a href="https://libcheck.github.io/check/">проверка</a> ; список структур модульного тестирования в c можно найти <a href="http://check.sourceforge.net/doc/check\_html/check\_2.html#sec3">здесь</a> и воспроизводится ниже. в зависимости от того, сколько стандартных функций библиотеки имеет ваша среда выполнения, вы можете или не сможете использовать одну из них.</p><blockquote> <h3>aceunit</h3> <p>aceunit (advanced c и embedded unit) позиционирует себя как удобную среду модульного тестирования кода c. он пытается имитировать junit 4.x и включает в себя возможности, подобные отражению. aceunit может использоваться в средах с ограниченными ресурсами, например, разработка встроенного программного обеспечения, и, что важно, он отлично работает в средах, где вы не можете включить один стандартный файл заголовка и не можете вызвать одну стандартную функцию c из библиотек ansi/iso c. у этого также есть порт windows. он не использует вилки для захвата сигналов, хотя авторы выразили заинтересованность в добавлении такой функции. смотрите <a href="http://aceunit.sourceforge.net/">домашняя страница aceunit</a> .</p> <h3>gnu autounit</h3> <p>во многом по той же схеме, что и check, включая разветвление для запуска модульных тестов в отдельном адресном пространстве (фактически, первоначальный автор check заимствовал эту идею из gnu autounit). gnu autounit широко использует glib, что означает, что для линковки и тому подобного нужны специальные опции, но это может не составить вам большой проблемы, особенно если вы уже используете gtk или glib. смотрите <a href="http://autounit.tigris.org/">домашняя страница gnu autounit</a> .</p> <h3>куните</h3> <p>также использует glib, но не разветвляется для защиты адресного пространства модульных тестов.</p> <h3>куните</h3> <p>стандартный c, с планами по реализации win32 gui. в настоящее время не разветвляется или иным образом не защищает адресное пространство модульных тестов в начале разработки. смотрите <a href="http://cunit.sourceforge.net/">cunit homepage</a> .</p> <h3>симпатичных</h3> <p>простая структура с одним .c и одним .h файлом, который вы перетаскиваете в дерево исходных текстов. смотрите <a href="http://cutest.sourceforge.net/">домашняя страница cutest</a> .</p> <h3>cppunit</h3> <p>основа для модульного тестирования c++; вы также можете использовать его для тестирования кода c. он стабилен, активно развивается и имеет графический интерфейс. основные причины не использовать cppunit для c: во-первых, он довольно большой, а во-вторых, вы должны писать свои тесты на c++, что означает, что вам нужен компилятор c++. если это не похоже на проблемы, это, безусловно, стоит рассмотреть, наряду с другими средами модульного тестирования c++. смотрите <a href="http://cppunit.sourceforge.net/doc/cvs/index.html">домашняя страница cppunit</a> .</p> <h3>embunit</h3> <p>embunit (embedded unit) - это еще одна инфраструктура модульного тестирования для встроенных систем. этот, кажется, заменен aceunit. <a href="http://sourceforge.net/projects/embunit/">домашняя страница встроенного блока</a> .</p> <h3>minunit</h3> <p>минимальный набор макросов и все! суть в том, чтобы показать, как легко выполнить модульное тестирование вашего кода. смотрите <a href="http://www.jera.com/techinfo/jtns/jtn002.html">minunit homepage</a> .</p> <h3>блок для мистера андо</h3> <p>реализация cunit, которая является довольно новой и, видимо, все еще находится на ранней стадии разработки. смотрите <a href="http://park.ruru.ne.jp/ando/work/cunitforando/html/">cunit для главной страницы mr. ando</a> .</p> <p><em> этот список последний раз обновлялся в марте 2008 года. </em></p> </blockquote><h2>больше рамок:</h2><h3>cmocka</h3><p>cmocka - это тестовая среда для c с поддержкой фиктивных объектов. это просто в использовании и настройке.</p><p>смотрите <a href="https://cmocka.org/">домашняя страница cmocka</a> .</p><h3>критерий</h3><p>criterion - это кроссплатформенная инфраструктура модульного тестирования c, поддерживающая автоматическую регистрацию тестов, параметризованные тесты, теории и способная выводить данные в несколько форматов, включая tap и junit xml. каждый тест выполняется в своем собственном процессе, поэтому при необходимости можно сообщать о сигналах и сбоях.</p><p>смотрите <a href="https://github.com/snaipe/criterion">домашняя страница критерия</a> для получения дополнительной информации.</p><h3>hwut</h3><p>hwut - это общий инструмент модульного тестирования с отличной поддержкой c. он может помочь создавать make-файлы, генерировать массивные тестовые примеры, закодированные в минимальных "таблицах итераций", проходить по конечным автоматам, генерировать c-заглушки и многое другое. общий подход довольно уникален: вердикты основаны на "хороший стандартный вывод/плохой стандартный вывод". функция сравнения, однако, является гибкой. таким образом, любой тип сценария может быть использован для проверки. это может быть применено к любому языку, который может производить стандартный вывод.</p><p>смотрите <a href="http://hwut.sourceforge.net/">домашняя страница hwut</a> .</p><h3>cgreen</h3><p>современный, переносимый, кросс-языковой модуль для тестирования и макетирования c и c++. он предлагает дополнительную нотацию bdd, библиотеку-макет, возможность запускать ее в одном процессе (для облегчения отладки). доступен тестовый прогон, который автоматически обнаруживает функции теста. но вы можете создавать свои собственные программно.</p><p>все эти функции (и многое другое) описаны в <a href="https://cgreen-devs.github.io/">руководство cgreen</a> .</p><p>википедия дает подробный список платформ модульного тестирования на c в разделе <a href="https://en.wikipedia.org/wiki/list\_of\_unit\_testing\_frameworks#c">список платформ модульного тестирования: c</a> </p>

<p>лично мне нравится <a href="http://code.google.com/p/googletest/">google test framework</a> .</p><p>реальная трудность в тестировании кода c состоит в нарушении зависимостей от внешних модулей, чтобы вы могли изолировать код в единицах. это может быть особенно проблематично, когда вы пытаетесь провести тестирование унаследованного кода. в этом случае я часто использую компоновщик для использования функций-заглушек в тестах.</p><p>это то, что люди имеют в виду, когда говорят о "<strong> швах </strong>". в c ваш единственный вариант - использовать препроцессор или компоновщик для макетирования ваших зависимостей.</p><p>типичный набор тестов в одном из моих проектов на c может выглядеть так:</p><pre><code>#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)); } </code></pre><p><strong> обратите внимание, что вы на самом деле включаете файл c, а не файл заголовка </strong>. это дает преимущество доступа ко всем статическим элементам данных. здесь я макет своего логгера (который может быть в logger.o и дает пустую реализацию. это означает, что тестовый файл компилируется и связывается независимо от остальной части кода и выполняется изолированно.</p><p>что касается кросс-компиляции кода, чтобы это работало, вам нужны хорошие средства на цели. я сделал это с помощью googletest, скомпилированного для linux на архитектуре powerpc. это имеет смысл, потому что у вас есть полная оболочка и ос для сбора ваших результатов. для менее богатых сред (которые я классифицирую как что-либо без полноценной ос) вы должны просто собрать и запустить на хосте. вы должны сделать это в любом случае, чтобы вы могли запускать тесты автоматически как часть сборки.</p><p>я считаю, что тестирование кода на c++, как правило, намного проще из-за того, что код oo, как правило, гораздо менее связан, чем процедурный (конечно, это сильно зависит от стиля кодирования). также в c++ вы можете использовать приемы, такие как внедрение зависимостей и переопределение методов, чтобы получить швы в код, который инкапсулируется в противном случае.</p><p>у майкла фезерса есть <a href="https://rads.stackoverflow.com/amzn/click/com/0131177052">отличная книга о тестировании устаревшего кода</a> . в одной главе он описывает методы работы с не-oo-кодом, которые я настоятельно рекомендую.</p><p><strong> редактировать </strong>: я написал <a href="http://meekrosoft.wordpress.com/2009/11/09/unit-testing-c-code-with-the-googletest-framework/">сообщение в блоге</a> о процедурном коде модульного тестирования, с <a href="http://github.com/meekrosoft/helloc">источник доступен на github</a> .</p><p><strong> редактировать </strong>: есть <a href="http://pragprog.com/titles/jgade/test-driven-development-for-embedded-c">новая книга, выпускаемая прагматичными программистами</a> , которая конкретно посвящена модульному тестированию кода c, который <a href="http://meekrosoft.wordpress.com/2011/03/25/book-review-test-driven-development-for-embedded-c-beta/">я очень рекомендую</a> .</p>

<p> <a href="http://www.jera.com/techinfo/jtns/jtn002.html">minunit</a> - невероятно простая структура модульного тестирования. я использую его для модульного тестирования кода микроконтроллера для avr.</p>

<p>в настоящее время я использую среду модульного тестирования cutest:</p><p> <a href="http://cutest.sourceforge.net/">http://cutest.sourceforge.net/</a> </p><p>он идеально подходит для встраиваемых систем, поскольку он очень легкий и простой. у меня не было проблем, чтобы заставить его работать на целевой платформе, а также на рабочем столе. в дополнение к написанию модульных тестов все, что требуется, это:</p><ul> <li>файл заголовка включен везде, где вы вызываете подпрограммы cutest</li> <li>один дополнительный файл 'c' для компиляции/ссылки на изображение</li> <li>некоторый простой код добавлен в main для настройки и вызова модульных тестов - я просто использую это в специальной функции main (), которая компилируется, если во время сборки определен unittest.</li> </ul><p>система должна поддерживать кучу и некоторую функциональность stdio (что есть не во всех встроенных системах). но код достаточно прост, чтобы вы могли работать в альтернативах этим требованиям, если у вашей платформы их нет.</p><p>при некотором разумном использовании внешних блоков "c" {} он также прекрасно поддерживает тестирование c++.</p>

<p>я говорю почти так же, как ratkok, но если у вас есть встроенный поворот для модульных тестов, то ...</p><p> <a href="http://www.throwtheswitch.org/unity/">nity</a> - настоятельно рекомендуемая среда для модульного тестирования c-кода.</p><p>примеры в книге, упомянутой в этой теме <a href="http://pragprog.com/titles/jgade/test-driven-development-for-embedded-c">tdd для встроенного c</a> , написаны с использованием unity (и cpputest).</p>

<p>возможно, вы также захотите взглянуть на <a href="https://github.com/zorgnax/libtap">libtap</a> , среду тестирования c, которая выводит протокол test anything protocol (tap) и, таким образом, хорошо интегрируется с различными инструментами, выходящими для этой технологии. он в основном используется в динамическом мире языков, но он прост в использовании и становится очень популярным.</p><p>пример:</p><pre><code>#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 с поддержкой фиктивных объектов, называемая <a href="http://cmocka.org/">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); }  <a href="http://api.cmocka.org/">api полностью задокументировано, и несколько примеров являются частью исходного кода.для начала работы с cmocka вы должны прочитать статью на lwn.net: <a href="https://lwn.net/articles/558106/">модульное тестирование с фиктивными объектами в c cmocka 1.0 была выпущена в феврале 2015 года.

я не стал долго тестировать устаревшее приложение c, прежде чем начал искать способ имитации функций. мне были нужны насмешки, чтобы изолировать c-файл, который я хочу проверить, от других. я дал cmock попытку, и я думаю, что приму это.cmock сканирует заголовочные файлы и генерирует фиктивные функции на основе найденных им прототипов. насмешки позволят вам протестировать файл c в полной изоляции. все, что вам нужно сделать, это связать ваш тестовый файл с макетами вместо ваших реальных объектных файлов.еще одним преимуществом cmock является то, что он будет проверять параметры, передаваемые имитируемым функциям, и позволит вам указать, какое возвращаемое значение должно предоставлять mocks. это очень полезно для проверки различных потоков исполнения в ваших функциях.тесты состоят из типичных функций testa (), testb (), в которых вы строите ожидания, вызываете функции для тестирования и проверки утверждений.последний шаг - создать бегуна для ваших тестов с единством. cmock связан со структурой тестирования единства. unity так же легко изучить, как и любой другой фреймворк.стоит попробовать и довольно легко понять: <a href="http://sourceforge.net/apps/trac/cmock/wiki">http://sourceforge.net/apps/trac/cmock/wiki <strong> обновление 1 </strong>еще одна структура, которую я исследую, - это cmockery. <a href="http://code.google.com/p/cmockery/">http://code.google.com/p/cmockery/ это чистый c-фреймворк, поддерживающий модульное тестирование и макетирование. он не зависит от ruby (в отличие от cmock) и очень мало зависит от внешних библиотек.для настройки макетов требуется немного больше ручной работы, потому что он не генерирует код. это не представляет большой работы для существующего проекта, так как прототипы не сильно изменятся: если у вас есть макеты, вам не нужно будет их менять некоторое время (это мой случай). дополнительный набор текста обеспечивает полный контроль над макетами. если есть что-то, что вам не нравится, вы просто меняете свой макет.нет необходимости в специальном тесте. вам нужно только создать массив тестов и передать его в функцию run_tests. здесь тоже немного больше ручной работы, но мне определенно нравится идея автономной автономной структуры.кроме того, он содержит некоторые изящные трюки c, которых я не знал.в целом cmockery нужно немного больше понимать, что такое макеты, чтобы начать. примеры должны помочь вам преодолеть это. похоже, что он может сделать работу с более простой механикой.

как новичок в c, я обнаружил, что слайды, называемые <a href="http://www.slideshare.net/amritayan/test-driven-development-in-c"><strong> разработка, управляемая тестами в c </strong> , очень полезны. по сути, он использует стандартную assert() вместе с && для доставки сообщения без каких-либо внешних зависимостей. если кто-то привык к фреймворку полного стека, это, вероятно, не сработает :)

я не использую фреймворк, я просто использую autotools "check" target support. реализуйте "main" и используйте assert (s).мой тестовый каталог makefile.am выглядит так: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 

существует <a href="http://cunit.sourceforge.net/"><strong> cunit </strong> и <a href="https://sourceforge.net/projects/embunit/"><strong> embedded unit </strong> является структурой модульного тестирования для embedded c system. его дизайн был скопирован с junit и cunit и более, а затем несколько адаптирован для embedded c system. встроенный модуль не требует стандартных библиотек. все объекты размещены в постоянной области.и <a href="http://www.hitex.de/perm/tessy.htm"><strong> tessy </strong> автоматизирует модульное тестирование встроенного программного обеспечения.

мы написали <a href="http://users.jyu.fi/~sapekiis/cheat/">cheat (размещено на <a href="http://github.com/tuplanolla/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 </code></pre><p>у него тоже красивые цвета.</p>

<p>в книге майкла фезера "эффективная работа с устаревшим кодом" представлено множество методов, специфичных для модульного тестирования во время разработки на си.</p><p>существуют методы, связанные с внедрением зависимостей, специфичные для c, которых я больше нигде не видел.</p>

<p> <a href="http://www.cpputest.org/">cpputest</a> - настоятельно рекомендуемая среда для модульного тестирования c-кода.</p><p>примеры в книге, упомянутой в этой теме <a href="http://pragprog.com/titles/jgade/test-driven-development-for-embedded-c">tdd для встроенного c</a> , написаны с использованием cpputest.</p>

<p>кроме моего очевидного уклона</p><p> <a href="http://code.google.com/p/seatest/">http://code.google.com/p/seatest/</a> </p><p>хороший простой способ модульного тестирования c-кода. подражает xunit</p>

<p>я использую <a href="http://cxxtest.tigris.org/">cxxtest</a> для встроенной среды c/c ++ (прежде всего c++).</p><p>я предпочитаю cxxtest, потому что у него есть скрипт на perl/python для сборки тестового прогона. после небольшого уклона, чтобы его настроить (еще меньше, так как вам не нужно писать тестовый прогон), его довольно легко использовать (включает примеры и полезную документацию). большая часть работы заключалась в настройке "аппаратного обеспечения", к которому обращается код, чтобы я мог эффективно тестировать модуль/модуль. после этого легко добавить новые тестовые случаи.</p><p>как упоминалось ранее, это среда модульного тестирования c/c++. так что вам понадобится компилятор c++.</p><p> <a href="http://cxxtest.sourceforge.net/guide.html">руководство пользователя cxxtest</a> <a href="http://cxxtest.com/index.php?title=main\_page">cxxtest wiki</a> </p>

<p>прочитав minunit, я подумал, что лучше использовать тестовый макрос в assert, который я часто использую, например, метод защитной программы. поэтому я использовал ту же идею minunit, смешанную со стандартным assert. вы можете увидеть мой фреймворк (хорошее имя может быть nominunit) в <a href="http://www.shike2.com/blog/2010/12/written-unit-test-using-c.html">блог k0ga</a> </p>

<p>у google отличная система тестирования. <a href="https://github.com/google/googletest/blob/master/googletest/docs/primer.md">https://github.com/google/googletest/blob/master/googletest/docs/primer.md</a> </p><p>и да, насколько я вижу, он будет работать с простым c, то есть не требует функций c++ (может потребоваться компилятор c++, не уверен).</p>

<p>cmockery на <a href="http://code.google.com/p/cmockery/">http://code.google.com/p/cmockery/</a> </p>

<p> <a href="https://github.com/google/cmockery">cmockery</a> - это недавно запущенный проект, который состоит из очень простой в использовании библиотеки c для написания модульных тестов.</p>

<p>сначала посмотрите здесь: <a href="http://en.wikipedia.org/wiki/list\_of\_unit\_testing\_frameworks#c">http://en.wikipedia.org/wiki/list\_of\_unit\_testing\_frameworks#c</a> </p><p>у моей компании есть библиотека c, которую используют наши клиенты. мы используем cxxtest (библиотека модульных тестов c++) для тестирования кода. cppunit также будет работать. если вы застряли в c, я бы порекомендовал rcunit (но cunit тоже хорош).</p>

<p>попробуйте lcut! - <a href="http://code.google.com/p/lcut">http://code.google.com/p/lcut</a> </p>

<p> <a href="http://lvc.github.io/api-sanity-checker/">api sanity checker</a> - тестовая среда для библиотек c/c++:</p><blockquote> <p>автоматический генератор базовых модульных тестов для общей библиотеки c/c++. он способен генерировать разумные (в большинстве, но, к сожалению, не во всех случаях) входные данные для параметров и составлять простые ("нормальные" или "поверхностные") тестовые случаи для каждой функции в api посредством анализа объявлений в заголовке файлы.</p> <p>качество генерируемых тестов позволяет проверять отсутствие критических ошибок в простых случаях использования. инструмент может создавать и выполнять сгенерированные тесты и обнаруживать сбои (segfaults), прерывания, все виды излучаемых сигналов, ненулевой код возврата программы и зависание программы.</p> </blockquote><p>примеры:</p><ul> <li> <a href="http://upstream-tracker.org/tests/fontconfig/2.8.0/view\_tests.html">набор тестов</a> для fontconfig 2.8.0</li> <li> <a href="http://upstream-tracker.org/tests/freetype2/2.4.8/view\_tests.html">набор тестов</a> для freetype 2.4.8</li> </ul>

<p>я использовал <a href="http://rcunit.sourceforge.net/">rcunit</a> , чтобы выполнить некоторое модульное тестирование встроенного кода на пк перед тестированием на целевой. хорошая абстракция аппаратного интерфейса важна, иначе регистры с порядком байтов и отображением памяти убьют вас.</p>

<p>если вы знакомы с junit, то я рекомендую cppunit. <a href="http://cppunit.sourceforge.net/cppunit-wiki">http://cppunit.sourceforge.net/cppunit-wiki</a> </p><p>это предполагает, что у вас есть компилятор c ++ для выполнения модульных тестов. если нет, то я должен согласиться с адамом розенфилдом, что чек - это то, что вы хотите.</p>

<p>libu ( <a href="http://koanlogic.com/libu">http://koanlogic.com/lib</a> ) имеет модуль модульного тестирования, который позволяет явно определять зависимости набора тестов/случаев, изоляцию тестов, параллельное выполнение и настраиваемый форматер отчетов (по умолчанию это xml и txt). ).</p><p>библиотека имеет лицензию bsd и содержит много других полезных модулей - сети, отладки, часто используемых структур данных, конфигурации и т.д. - если они понадобятся вам в ваших проектах ...</p>

<p>я удивлен, что никто не упомянул <a href="http://cutter.sourceforge.net/">cutter (http://cutter.sourceforge.net/)</a> вы можете протестировать c и c++, он легко интегрируется с autotools и имеет действительно хороший учебник.</p>

<p>один из способов - разработка кода модульного теста с использованием инфраструктуры c++ xunit (и компилятора c++), при этом исходный код целевой системы сохраняется в виде модулей c.</p><p>убедитесь, что вы регулярно компилируете исходный код c под свой кросс-компилятор, автоматически с вашими модульными тестами, если это возможно.</p>

<p>если вы все еще в поисках тестовых сред, <a href="http://code.google.com/p/cunitwin32/">cunitwin32</a> - это то, что нужно для платформы win32/nt.</p><p>это решает одну фундаментальную проблему, с которой я столкнулся в других средах тестирования. а именно глобальные/статические переменные находятся в детерминированном состоянии, потому что каждый тест выполняется как отдельный процесс.</p>

<p>если вы ориентируетесь на платформы win32 или режим ядра nt, вам следует взглянуть на <a href="http://cfix.sf.net/">cfix</a> .</p>

<p>я только что написал <a href="https://github.com/kirbyfan64/libcut">libcut</a> из-за разочарования в существующих библиотеках модульного тестирования си. он имеет автоматическое определение типа примитивов (нет необходимости в test\_eq\_int, test\_eq\_long, test\_eq\_short и т.д.; только два разных набора для примитивов и строк) и состоит из одного заголовочного файла. вот короткий пример:</p><pre><code>#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); </code></pre><p>это работает только с c11, хотя.</p>