Eenheidstest C-code

Ik heb deze zomer op een ingesloten systeem gewerkt in recht C. het was een bestaand project dat het bedrijf waarvoor ik werk overnam. Ik ben behoorlijk gewend geworden aan het schrijven van eenheidstests in Java met JUNIST, maar was op verlies met betrekking tot de beste manier om eenheidstests voor bestaande code te schrijven (die een refactoring nodig heeft) en nieuwe code toegevoegd aan het systeem.

Zijn er projecten die er zijn die eenheidstest Plain C-code testen zo eenvoudig als eenheidstest Java-code met JUNIST? Elk inzicht dat specifiek van toepassing zou zijn op embedded-ontwikkeling (cross-compiling voor arm-Linux-platform) zou zeer op prijs worden gesteld.


Antwoord 1, Autoriteit 100%

Eén eenheidstestkader in C is controle ; Een lijst met eenheidstestkaders in C is te vinden hier en wordt gereproduceerd onderstaand. Afhankelijk van het aantal standaard bibliotheekfuncties, kunt u of niet in staat zijn om een ​​van die te gebruiken.

ACEUNIT

AceUneit (geavanceerde C en ingesloten eenheid) Rekeningen zelf als een comfortabel C-code-eenheidstoetskader. Het probeert Junit 4.x te mimikken en bevat reflectieachtige capaciteiten. Aceuneit kan worden gebruikt in de omgevingen van de resource-constraint, b.v. Embedded Software Development, en is belangrijker, het werkt prima in omgevingen waarin u geen enkel standaard header-bestand kunt opnemen en een enkele standaard C-functie van de ANSI / ISO C-bibliotheken niet kunt oproepen. Het heeft ook een Windows-poort. Het gebruikt geen vorken om signalen te vangen, hoewel de auteurs interesse hebben uitgesproken in het toevoegen van een dergelijke functie. Zie de aceeuit homepage .

GNU AUTOUIT

Veel in dezelfde lijnen als cheque, inclusief forking om eenheidstests in een afzonderlijke adresruimte te gebruiken (in feite, de oorspronkelijke auteur van het controleren heeft het idee van GNU AUTOUITEIT geleend). GNU Autounit gebruikt GLIB uitgebreid, wat betekent dat koppeling en dergelijke speciale opties nodig hebben, maar dit is mogelijk geen groot probleem voor u, vooral als u al GTK of GLIB gebruikt. Zie de GNU AUTOUIT HOMEPAGE .

CUNIT

Gebruikt ook GLIB, maar vult niet om de adresruimte van eenheidstests te beschermen.

CUNIT

Standaard C, met plannen voor een WIN32 GUI-implementatie. MOMENT MOMENT MOMENTEEL of beschermt of anderszins de adresruimte van eenheidstests. In de vroege ontwikkeling. Zie de cunit homepage .

Cutest

Een eenvoudig raamwerk met slechts één .c en één .H-bestand dat u in uw bronboom laat vallen. Zie de leukste homepage .

CPUNIT

Het Premier Unit-testkader voor C++; U kunt het ook gebruiken om C-code te testen. Het is stabiel, actief ontwikkeld en heeft een GUI-interface. De belangrijkste redenen om CPPunit niet te gebruiken voor C zijn de eerste die het vrij groot is, en de tweede moet je je tests in C++ moeten schrijven, wat betekent dat je een C++-compiler nodig hebt. Als dit niet klinkt als zorgen, is het zeker de moeite waard om te overwegen, samen met andere C++ -eenheidstestkaders. Zie de cppunit homepage .

Embunit

EMBUNIT (embedded-eenheid) is een ander eenheidstestkader voor ingebedde systemen. Deze lijkt te worden vervangen door Aceuit. embedded unit startpagina .

Minunit

Een minimale set macro’s en dat is alles! Het punt is om te laten zien hoe gemakkelijk het is om uw code te testen. Zie de MinUnit-startpagina.

CUnit voor Mr. Ando

Een CUnit-implementatie die vrij nieuw is en blijkbaar nog in de kinderschoenen staat. Zie de CUnit for Mr. Ando homepage.

Deze lijst is voor het laatst bijgewerkt in maart 2008.

Meer kaders:

CMocka

CMocka is een testraamwerk voor C met ondersteuning voor nepobjecten. Het is gemakkelijk te gebruiken en in te stellen.

Zie de CMocka-startpagina.

Criterium

Criterion is een platformonafhankelijk testraamwerk voor C-eenheden dat automatische testregistratie, geparametriseerde tests en theorieën ondersteunt en dat naar meerdere formaten kan worden uitgevoerd, waaronder TAP en JUnit XML. Elke test wordt in zijn eigen proces uitgevoerd, zodat signalen en crashes indien nodig kunnen worden gerapporteerd of getest.

Zie de Criterion-startpaginavoor meer informatie.

HWUT

HWUT is een algemene tool voor het testen van eenheden met geweldige ondersteuning voor C. Het kan helpen om Makefiles te maken, enorme testgevallen te genereren die zijn gecodeerd in minimale ‘iteratietabellen’, langs staatsmachines te lopen, C-stubs te genereren en meer. De algemene benadering is vrij uniek: uitspraken zijn gebaseerd op ‘good stdout/bad stdout’. De vergelijkingsfunctie is echter flexibel. Elk type script kan dus worden gebruikt voor controle. Het kan worden toegepast op elke taal die standaarduitvoer kan produceren.

Zie de HWUT-startpagina.

CGroen

Een modern, draagbaar, meertalig raamwerk voor het testen en bespotten van eenheden voor C en C++. Het biedt een optionele BDD-notatie, een mocking-bibliotheek, de mogelijkheid om het in een enkel proces uit te voeren (om debuggen gemakkelijker te maken). Er is een testloper beschikbaar die automatisch de testfuncties ontdekt. Maar u kunt uw eigen programma’s maken.

Al deze functies (en meer) worden uitgelegd in de CGreen-handleiding.

Wikipedia geeft een gedetailleerde lijst van C unit testing frameworks onder Lijst van unit testing frameworks: C


Antwoord 2, autoriteit 34%

Persoonlijk vind ik het Google Test-frameworkgoed.

De echte moeilijkheid bij het testen van C-code is het doorbreken van de afhankelijkheden van externe modules, zodat je code in eenheden kunt isoleren. Dit kan met name problematisch zijn wanneer u tests probeert uit te voeren rond oude code. In dit geval merk ik dat ik vaak de linker gebruik om stubs-functies in tests te gebruiken.

Dit is waar mensen naar verwijzen als ze het hebben over “naden“. In C is je enige optie echt om de pre-processor of de linker te gebruiken om je afhankelijkheden te bespotten.

Een typische testsuite in een van mijn C-projecten kan er als volgt uitzien:

#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));
}

Merk op dat je eigenlijk het C-bestand opneemt en niet het headerbestand. Dit geeft het voordeel van toegang tot alle statische gegevensleden. Hier bespot ik mijn logger (die mogelijk in logger.o staat en een lege implementatie geeft. Dit betekent dat het testbestand onafhankelijk van de rest van de codebasis wordt gecompileerd en gekoppeld en geïsoleerd wordt uitgevoerd.

Wat betreft het cross-compileren van de code, om dit te laten werken, heb je goede faciliteiten op het doel nodig. Ik heb dit gedaan met googletest cross gecompileerd naar Linux op een PowerPC-architectuur. Dit is logisch, want daar heb je een volledige schaal en os om je resultaten te verzamelen. Voor minder rijke omgevingen (die ik classificeer als alles zonder een volledig besturingssysteem) moet je gewoon bouwen en draaien op de host. Je moet dit hoe dan ook doen, zodat je de tests automatisch kunt uitvoeren als onderdeel van de build.

Ik vind het testen van C++-code over het algemeen veel gemakkelijker vanwege het feit dat OO-code over het algemeen veel minder gekoppeld is dan procedureel (dit hangt natuurlijk sterk af van de coderingsstijl). Ook in C++ kun je trucs gebruiken zoals afhankelijkheidsinjectie en methode-overriding om naden in code te krijgen die anders ingekapseld is.

Michael Feathers heeft een uitstekend boek over het testen van legacy code. In een hoofdstuk behandelt hij technieken voor het omgaan met niet-OO-code die ik ten zeerste aanbeveel.

Bewerken: ik heb een blogberichtover procedurecode voor het testen van eenheden, met bron beschikbaar op GitHub.

Bewerken: er is een nieuw boek van de Pragmatic Programmersdat specifiek ingaat op unit testing C-code die Ik raad het ten zeerste aan.


Antwoord 3, autoriteit 27%

Minunitis een ongelooflijk eenvoudig raamwerk voor het testen van eenheden.
Ik gebruik het om de c-microcontrollercode voor avr te testen.


Antwoord 4, autoriteit 8%

Ik zeg bijna hetzelfde als ratkok, maar als je een ingebedde draai aan de unit-tests hebt, dan…

Unity– Sterk aanbevolen framework voor unit testing C-code.

#include <unity.h>
void test_true_should_be_true(void)
{
    TEST_ASSERT_TRUE(true);
}
int main(void)
{
    UNITY_BEGIN();
    RUN_TEST(test_true_should_be_true);
    return UNITY_END();
}

De voorbeelden in het boek dat in deze thread wordt genoemd TDD voor embedded Czijn geschreven met Unity (en CppUTest).


Antwoord 5, autoriteit 8%

Ik gebruik momenteel het CuTest unit test framework:

http://cutest.sourceforge.net/

Het is ideaal voor embedded systemen omdat het erg licht en eenvoudig is. Ik had geen problemen om het zowel op het doelplatform als op de desktop te laten werken. Naast het schrijven van de unit-tests, is het enige dat nodig is:

  • een header-bestand dat overal is opgenomen
    je noemt de CuTest-routines
  • een enkel extra ‘C’-bestand moet worden
    gecompileerd/gelinkt in de afbeelding
  • een paar simpele code toegevoegd aan main to
    de unit-tests instellen en oproepen – I
    zet dit gewoon in een speciale main()
    functie die wordt gecompileerd als
    UNITTEST wordt gedefinieerd tijdens de
    bouwen.

Het systeem moet een hoop en wat stdio-functionaliteit ondersteunen (die niet alle embedded systemen hebben). Maar de code is zo eenvoudig dat u waarschijnlijk in alternatieven voor die vereisten zou kunnen werken als uw platform ze niet heeft.

Met enig oordeelkundig gebruik van externe “C”{}-blokken ondersteunt het ook prima het testen van C++.


Antwoord 6, autoriteit 7%

Misschien wil je ook eens kijken naar libtap, een C-testraamwerk dat de Test Anything uitvoert Protocol (TAP) en integreert dus goed met een verscheidenheid aan tools die voor deze technologie uitkomen. Het wordt meestal gebruikt in de dynamische taalwereld, maar het is gemakkelijk te gebruiken en wordt steeds populairder.

Een voorbeeld:

#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();
}

Antwoord 7, autoriteit 5%

Er is een elegant raamwerk voor het testen van eenheden voor C met ondersteuning voor nepobjecten genaamd cmocka. Het vereist alleen de standaard C-bibliotheek, werkt op een reeks computerplatforms (inclusief embedded) en met verschillende compilers.

Het heeft ook ondersteuning voor verschillende berichtuitvoerformaten zoals Subunit, Test Anything Protocol en jUnit XML-rapporten.

cmocka is gemaakt om ook op embedded platforms te werken en heeft ook Windows-ondersteuning.

Een eenvoudige test ziet er als volgt uit:

#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);
}

De APIis volledig gedocumenteerd en verschillende voorbeelden maken deel uit van de broncode.

Om met cmocka aan de slag te gaan, moet u het artikel op LWN.net lezen: Eenheidstest met nepobjecten in C

cmocka 1.0 is uitgebracht in februari 2015.


Antwoord 8, autoriteit 4%

Ik kwam niet ver met het testen van een verouderde C-toepassing voordat ik op zoek ging naar een manier om functies te spotten. Ik had de spot hard nodig om het C-bestand dat ik wil testen te isoleren van anderen. Ik heb cmock geprobeerd en ik denk dat ik het zal adopteren.

Cmock scant header-bestanden en genereert nepfuncties op basis van gevonden prototypes. Met Mocks kunt u een C-bestand in perfecte isolatie testen. Het enige wat u hoeft te doen is uw testbestand te koppelen aan mocks in plaats van uw echte objectbestanden.

Een ander voordeel van cmock is dat het de parameters valideert die zijn doorgegeven aan gesimuleerde functies, en u kunt specificeren welke retourwaarde de mocks moeten bieden. Dit is erg handig om verschillende uitvoeringsstromen in uw functies te testen.

Tests bestaan uit de typische testA(), testB()-functies waarin u verwachtingen bouwt, functies aanroept om te testen en beweringen te controleren.

De laatste stap is het genereren van een runner voor uw tests met eenheid. Cmock is gekoppeld aan het unity-testraamwerk. Unity is net zo gemakkelijk te leren als elk ander unit-testraamwerk.

Zeker het proberen waard en vrij gemakkelijk te begrijpen:

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

Update 1

Een ander raamwerk dat ik onderzoek is Cmockery.

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

Het is een puur C-framework dat unit testing en mocking ondersteunt. Het is niet afhankelijk van ruby (in tegenstelling tot Cmock) en het is zeer weinig afhankelijk van externe bibliotheken.

Het vereist wat meer handmatig werk om mocks in te stellen, omdat er geen code wordt gegenereerd. Dat is niet veel werk voor een bestaand project, aangezien prototypes niet veel zullen veranderen: als je eenmaal je mocks hebt, hoef je ze een tijdje niet te veranderen (dit is mijn geval). Extra typen biedt volledige controle over mocks. Als er iets is dat je niet leuk vindt, verander je gewoon je mock.

Geen speciale testloper nodig. U hoeft alleen een reeks tests te maken en deze door te geven aan een run_tests-functie. Hier ook wat meer handwerk, maar ik hou zeker van het idee van een op zichzelf staand autonoom raamwerk.

Bovendien bevat het een aantal handige C-trucs die ik niet kende.

Over het algemeen heeft Cmockery wat meer begrip van mocks nodig om te beginnen. Voorbeelden zouden u moeten helpen dit te overwinnen. Het lijkt erop dat het het werk kan doen met eenvoudigere mechanica.


Antwoord 9, autoriteit 3%

We schreven CHEAT(gehost op GitHub) voor eenvoudige bruikbaarheid en draagbaarheid.

Het heeft geen afhankelijkheden en vereist geen installatie of configuratie.
Alleen een headerbestand en een testcase zijn nodig.

#include <cheat.h>
CHEAT_TEST(mathematics_still_work,
    cheat_assert(2 + 2 == 4);
    cheat_assert_not(2 + 2 == 5);
)

Tests worden gecompileerd tot een uitvoerbaar bestand dat zorgt voor het uitvoeren van de tests en het rapporteren van hun resultaten.

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

Het heeft ook mooie kleuren.


Antwoord 10, autoriteit 3%

Als C-beginner vond ik de dia’s met de naam Testgedreven ontwikkeling in Cerg behulpzaam. In principe gebruikt het de standaard assert()samen met &&om een bericht af te leveren, zonder enige externe afhankelijkheden. Als iemand gewend is aan een full-stack testraamwerk, zal dit waarschijnlijk niet werken 🙂


Antwoord 11, autoriteit 2%

Er is CUnit

En Embedded Unitis een unit-testraamwerk voor Embedded C-systeem. Het ontwerp is gekopieerd van JUnit en CUnit en meer, en vervolgens enigszins aangepast voor Embedded C-systeem. Embedded Unit vereist geen std C libs. Alle objecten worden toegewezen aan een constant gebied.

En Tessyautomatiseert het testen van eenheden van embedded software .


Antwoord 12, autoriteit 2%

Ik gebruik geen framework, ik gebruik alleen autotools om de doelondersteuning te “controleren”. Implementeer een “hoofd” en gebruik assert(en).

Mijn testmap Makefile.am(s) ziet er als volgt uit:

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

Antwoord 13, autoriteit 2%

Michael Feather’s boek “Effectief werken met oude code” bevat veel technieken die specifiek zijn voor unit-testen tijdens C-ontwikkeling.

Er zijn technieken met betrekking tot afhankelijkheidsinjectie die specifiek zijn voor C en die ik nergens anders heb gezien.


Antwoord 14

CppUTest– Sterk aanbevolen framework voor unit testing C-code.

De voorbeelden in het boek dat in deze thread wordt genoemd TDD voor embedded Czijn geschreven met CppUTest.


Antwoord 15

Ik gebruik CxxTestvoor een embedded c/c++-omgeving (voornamelijk C++).

Ik geef de voorkeur aan CxxTest omdat het een perl/python-script heeft om de testrunner te bouwen. Na een kleine helling om het op te zetten (nog kleiner omdat je de testrunner niet hoeft te schrijven), is het vrij eenvoudig te gebruiken (inclusief voorbeelden en nuttige documentatie). Het meeste werk was het opzetten van de ‘hardware’ waartoe de code toegang heeft, zodat ik eenheden/modules effectief kon testen. Daarna is het eenvoudig om nieuwe unit-testcases toe te voegen.

Zoals eerder vermeld, is het een C/C++ unit-testraamwerk. Je hebt dus een C++-compiler nodig.

CxxTest-gebruikershandleiding
CxxTest Wiki


Antwoord 16

anders dan mijn duidelijke vooroordeel

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

is een leuke, eenvoudige manier om C-code te testen. bootst xUnit na


Antwoord 17

Na het lezen van Minunit dacht ik dat het een betere manier was om de test te baseren op een assert-macro, die ik veel gebruik als defensieve programmatechniek. Dus ik gebruikte hetzelfde idee van Minunit vermengd met standaard assert. Je kunt mijn raamwerk zien (een goede naam zou NoMinunit kunnen zijn) in blog van k0ga


Antwoord 18

Google heeft een uitstekend testkader. https://github.com/google/googletest/blob/ master/googletest/docs/primer.md

En ja, voor zover ik zie, werkt het met gewone C, d.w.z. vereist geen C++-functies (mogelijk een C++-compiler nodig, niet zeker).


Antwoord 19

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


Antwoord 20

Cmockeryis een recent gelanceerd project dat bestaat uit een zeer eenvoudig te gebruiken C-bibliotheek voor schrijfeenheid testen.


Antwoord 21

Kijk eerst hier: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks# C

Mijn bedrijf heeft een C-bibliotheek die onze klanten gebruiken. We gebruiken CxxTest (een C++ unit-testbibliotheek) om de code te testen. CppUnit zal ook werken. Als je vastzit in C, raad ik RCUNIT aan (maar CUnit is ook goed).


Antwoord 22

Als je bekend bent met JUnit, raad ik CppUnit aan.
http://cppunit.sourceforge.net/cppunit-wiki

Dat veronderstelt dat je een c++-compiler hebt om de unit-tests uit te voeren. zo niet, dan moet ik het eens zijn met Adam Rosenfield dat cheque is wat je wilt.


Antwoord 23

Ik heb RCUNITgebruikt om enkele unit-tests uit te voeren voor embedded code op pc voordat ik op het doel testte. Een goede abstractie van de hardware-interface is belangrijk, anders gaan endianness en memory-mapped registers je dood.


Antwoord 24

probeer lcut! – http://code.google.com/p/lcut


Antwoord 25

API Sanity Checker— testraamwerk voor C/C++-bibliotheken:

Een automatische generator van basiseenheidstests voor een gedeelde C/C++-bibliotheek. Het is in staat om redelijke (in de meeste, maar helaas niet alle, gevallen) invoergegevens voor parameters te genereren en eenvoudige (“sanity” of “ondiepe” kwaliteit) testgevallen voor elke functie in de API samen te stellen door de analyse van declaraties in de header bestanden.

De kwaliteit van gegenereerde tests maakt het mogelijk om de afwezigheid van kritieke fouten in eenvoudige gebruikssituaties te controleren. De tool is in staat om gegenereerde tests te bouwen en uit te voeren en crashes (segfaults), aborts, allerlei uitgezonden signalen, niet-nul programma-retourcode en programma-hanging te detecteren.

Voorbeelden:


Antwoord 26

Een techniek om te gebruiken is om de unit-testcode te ontwikkelen met een C++ xUnit-framework (en C++-compiler), terwijl de bron voor het doelsysteem als C-modules behouden blijft.

Zorg ervoor dat u uw C-bron regelmatig compileert onder uw cross-compiler, indien mogelijk automatisch met uw unit-tests.


Antwoord 27

LibU (http://koanlogic.com/libu) heeft een unit-testmodule die expliciete tests mogelijk maakt suite/case-afhankelijkheden, testisolatie, parallelle uitvoering en een aanpasbare rapportformatter (standaardformaten zijn xml en txt).

De bibliotheek heeft een BSD-licentie en bevat vele andere nuttige modules – netwerken, debuggen, veelgebruikte datastructuren, configuratie, enz. – mocht u ze nodig hebben in uw projecten …


Antwoord 28

Het verbaast me dat niemand Cutter (http://cutter.sourceforge.net/)noemde
Je kunt C en C++ testen, het integreert naadloos met autotools en er is een hele mooie tutorial beschikbaar.


Antwoord 29

Als je Win32-platforms of NT-kernelmodus target, moet je eens kijken naar cfix.


Antwoord 30

Als je nog steeds op zoek bent naar testframeworks, is CUnitWin32er een voor het Win32/NT-platform.

Dit lost een fundamenteel probleem op waarmee ik werd geconfronteerd met andere testkaders. Globale/statische variabelen bevinden zich namelijk in een deterministische toestand omdat elke test als een afzonderlijk proces wordt uitgevoerd.

Other episodes