it-swarm.it

Codice C di verifica Dell'unità

Ho lavorato su un sistema embedded questa estate scritto in linea C. Era un progetto esistente che la società per cui lavoravo aveva rilevato. Sono diventato abbastanza abituato a scrivere unit test in Java usando JUnit ma ero in perdita per quanto riguarda il modo migliore per scrivere test unitari per il codice esistente (che necessitava di refactoring) così come il nuovo codice aggiunto al sistema.

Esiste un modo per rendere semplice l'unità di test del codice C semplice come unità di test del codice Java con, per esempio, JUnit ? Qualsiasi intuizione che si applicherebbe specificamente allo sviluppo integrato (cross-compiling alla piattaforma arm-linux) sarebbe molto apprezzata.

805
Paul Osborne

Un framework di testing di unità in C è Check ; si può trovare una lista di quadri di test unitari in C here e viene riprodotto qui sotto. A seconda del numero di funzioni di libreria standard del runtime, è possibile o meno essere in grado di utilizzarne uno.

AceUnit

AceUnit (Advanced C e Embedded Unit) si autodefinisce come un comodo framework per il test delle unità di codice C. Cerca di imitare JUnit 4.x e include capacità di riflessione. AceUnit può essere utilizzato in ambienti con vincoli di risorse, ad es. sviluppo di software embedded e, soprattutto, funziona bene in ambienti in cui non è possibile includere un singolo file di intestazione standard e non è possibile richiamare una singola funzione C standard dalle librerie ANSI/ISO C. Ha anche una porta di Windows. Non usa le forcelle per intrappolare i segnali, anche se gli autori hanno espresso interesse ad aggiungere una funzione del genere. Vedi la homepage di AceUnit .

Autounità GNU

Molto simile a quello di Check, compreso il biforcarsi per eseguire test di unità in uno spazio di indirizzi separato (infatti, l'autore originale di Check ha preso in prestito l'idea da GNU Autounit). GNU Autounit usa GLib estensivamente, il che significa che il collegamento e tale necessità richiedono opzioni speciali, ma questo potrebbe non essere un grosso problema per te, specialmente se stai già utilizzando GTK o GLib. Vedi la GNU homepage Autounit .

cunit

Utilizza anche GLib, ma non si biforca per proteggere lo spazio degli indirizzi dei test unitari.

CUnit

Standard C, con piani per un'implementazione della GUI Win32. Al momento non esegue il fork o protegge in altro modo lo spazio degli indirizzi dei test unitari. Nel primo sviluppo. Vedi la homepage di CUnit .

Cutest

Un semplice framework con un solo file .c e un file .h da inserire nell'albero dei sorgenti. Vedi la homepage di CuTest .

CppUnit

Il principale framework di test unitario per C++; puoi anche usarlo per testare il codice C. È stabile, attivamente sviluppato e ha un'interfaccia GUI. I motivi principali per non usare CppUnit per C sono innanzitutto che è piuttosto grande, e in secondo luogo devi scrivere i tuoi test in C++, il che significa che hai bisogno di un compilatore C++. Se questi non sembrano preoccupanti, vale sicuramente la pena di prenderlo in considerazione, insieme ad altri framework di test delle unità C++. Vedi la homepage di CppUnit .

embUnit

embUnit (Embedded Unit) è un altro framework di test unitario per sistemi embedded. Questo sembra essere sostituito da AceUnit. Homepage Unità incorporata .

MinUnit

Un set minimo di macro e il gioco è fatto! Il punto è mostrare quanto è facile testare il codice dell'unità. Vedi la homepage di MinUnit .

CUnit per Mr. Ando

Un'implementazione di CUnit che è abbastanza nuova e apparentemente ancora in fase di sviluppo iniziale. Vedi la homepage di CUnit for Mr. Ando .

Questo elenco è stato aggiornato l'ultima volta nel marzo 2008.

Più quadri:

CMocka

CMocka è un framework di test per C con supporto per oggetti finti. È facile da usare e configurare.

Vedi la homepage di CMocka .

Criterio

Il criterio è un framework di test delle unità C multipiattaforma che supporta la registrazione automatica dei test, i test parametrizzati, le teorie e che può essere esportato in più formati, tra cui TAP e JUnit XML. Ogni test viene eseguito nel proprio processo, quindi segnali e arresti anomali possono essere segnalati o testati se necessario.

Vedi la homepage di Criterion per maggiori informazioni.

HWUT

HWUT è uno strumento di unit test generale con un grande supporto per C. Può aiutare a creare Makefile, generare enormi casi di test codificati in "tabelle di iterazione" minime, camminare su macchine a stati, generare C-stub e altro. L'approccio generale è piuttosto unico: i verdetti si basano sul "buon stdout/cattivo stdout". La funzione di confronto, tuttavia, è flessibile. Pertanto, qualsiasi tipo di script può essere utilizzato per il controllo. Può essere applicato a qualsiasi lingua che possa produrre output standard.

Vedi la homepage di HWUT .

Cgreen

Un moderno e portatile sistema per il testing e la simulazione di unità di linguaggio incrociato per C e C++. Offre una notazione BDD opzionale, una libreria di derisione, la possibilità di eseguirla in un unico processo (per semplificare il debug). Un test runner che rileva automaticamente le funzioni di test è disponibile. Ma puoi crearne di tuoi a livello di programmazione.

Tutte queste caratteristiche (e altro) sono spiegate nel il manuale CGreen .

Wikipedia fornisce un elenco dettagliato dei framework di test dell'unità C sotto Elenco dei framework di test unitari: C

461
Adam Rosenfield

Personalmente mi piace il framework di Google Test .

La vera difficoltà nel test del codice C è la rottura delle dipendenze su moduli esterni in modo da poter isolare il codice in unità. Questo può essere particolarmente problematico quando si sta tentando di eseguire test intorno al codice legacy. In questo caso mi capita spesso di utilizzare il linker per utilizzare le funzioni di stub nei test.

Questo è ciò a cui le persone si riferiscono quando parlano di " seams ". In C l'unica opzione è usare il pre-processore o il linker per prendere in giro le tue dipendenze.

Una tipica suite di test in uno dei miei progetti C potrebbe essere simile a questa:

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

Nota che stai effettivamente includendo il file C e non il file di intestazione . Ciò offre il vantaggio dell'accesso a tutti i membri dei dati statici. Qui metto in pausa il mio logger (che potrebbe essere nel logger.o e dare un'implementazione vuota. Ciò significa che il file di test compila e collega in modo indipendente dal resto del codice di base ed esegue in isolamento.

Per quanto riguarda la compilazione incrociata del codice, affinché funzioni, sono necessarie buone strutture sul target. L'ho fatto con googletest cross compilato su Linux su un'architettura PowerPC. Questo ha senso perché ci sono una shell e un sistema operativo completi per raccogliere i risultati. Per gli ambienti meno ricchi (che classifico come qualcosa senza un sistema operativo completo), è sufficiente creare ed eseguire sull'host. Dovresti farlo comunque in modo da poter eseguire i test automaticamente come parte della build.

Trovo che testare il codice C++ sia in genere molto più semplice a causa del fatto che il codice OO è in generale molto meno abbinato rispetto a quello procedurale (ovviamente dipende molto dallo stile di codifica). Anche in C++ puoi usare trucchi come l'iniezione delle dipendenze e il metodo di sovrascrivere per ottenere cuciture in codice che è altrimenti incapsulato.

Michael Feathers ha un libro eccellente sul test del codice legacy . In un capitolo tratta delle tecniche per trattare il codice non OO che consiglio vivamente.

Modifica : Ho scritto un post di blog sul codice procedurale di test unitario, con source disponibile su GitHub .

Edit : Esiste un nuovo libro che esce dai Pragmatic Programmers che riguarda specificamente il codice C di test unitario che consiglio vivamente .

152
mikelong

Minunit è un framework di test unitario incredibilmente semplice. Lo sto usando per il codice microcontroller test unit c per avr.

128
Matteo Caprari

Attualmente sto usando il framework di test dell'unità CuTest:

http://cutest.sourceforge.net/

È ideale per i sistemi embedded poiché è molto leggero e semplice. Non ho avuto problemi a farlo funzionare sulla piattaforma di destinazione e sul desktop. Oltre a scrivere i test unitari, tutto ciò che serve è:

  • un file di intestazione incluso ovunque tu stia chiamando le routine di CuTest
  • un singolo file 'C' aggiuntivo da compilare/collegare nell'immagine
  • qualche semplice codice aggiunto al main per impostare e chiamare i test di unità - ho solo questo in una funzione main () speciale che viene compilata se UNITTEST viene definito durante la build.

Il sistema deve supportare un heap e alcune funzionalità di stdio (che non tutti hanno i sistemi incorporati). Ma il codice è abbastanza semplice che potresti probabilmente lavorare in alternativa a quei requisiti se la tua piattaforma non li possiede.

Con un uso giudizioso dei blocchi "C" di extern {}, supporta anche il testing di C++.

40
Michael Burr

Dico quasi la stessa ratkok, ma se hai una svolta nei test unitari allora ...

Unity - Quadro altamente raccomandato per il test del codice C dell'unità.

Gli esempi nel libro menzionato in questo thread TDD per C embedded sono scritti usando Unity (e CppUTest).

36
Johan

Si potrebbe anche voler dare un'occhiata a libtap , un framework di test C che emette il Test Anything Protocol (TAP) e quindi si integra bene con una varietà di strumenti che escono per questa tecnologia. È usato principalmente nel mondo linguistico dinamico, ma è facile da usare e sta diventando molto popolare.

Un esempio:

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

C'è un elegante framework di test unitario per C con supporto per oggetti mock chiamati cmocka . Richiede solo la libreria C standard, funziona su una gamma di piattaforme di elaborazione (incluso embedded) e con diversi compilatori.

Supporta inoltre diversi formati di output dei messaggi come Subunit, Test Anything Protocol e jUnit XML reports.

cmocka è stato creato per funzionare anche su piattaforme embedded e ha anche il supporto di Windows.

Un semplice test assomiglia a questo:

#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 è completamente documentato e diversi esempi fanno parte del codice sorgente.

Per iniziare con cmocka dovresti leggere l'articolo su LWN.net: Test delle unità con oggetti mock in C

cmocka 1.0 è stato rilasciato a febbraio 2015.

26
asn

Non ho fatto molto per testare un'applicazione C legacy prima di iniziare a cercare un modo per simulare le funzioni. Mi servivano i mock male per isolare il file C che voglio testare dagli altri. Ho dato una prova di cmock e penso che lo adotterò.

Cmock analizza i file di intestazione e genera funzioni di simulazione basate sui prototipi che trova. Mock ti permetterà di testare un file C in perfetto isolamento. Tutto quello che dovrai fare è collegare il tuo file di test con mock invece dei tuoi file di oggetti reali.

Un altro vantaggio di cmock è che convaliderà i parametri passati a funzioni fittizie, e ti permetterà di specificare quale valore di ritorno dovrebbero fornire i mock. Questo è molto utile per testare diversi flussi di esecuzione nelle tue funzioni.

I test consistono nelle tipiche funzioni testA (), testB () in cui si creano aspettative, chiamate funzioni per testare e verificare asserzioni.

L'ultimo passo è generare un corridore per i tuoi test con l'unità. Cmock è legato alla struttura del test di unità. Unity è facile da apprendere come qualsiasi altro framework di test di unità.

Vale la pena provare e abbastanza facile da capire:

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

Aggiornamento 1

Un altro quadro che sto studiando è Cmockery.

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

Si tratta di un puro framework C che supporta il testing e la simulazione delle unità. Non ha dipendenza da Ruby (contrariamente a Cmock) e ha pochissima dipendenza dalle librerie esterne.

Richiede un po 'più di lavoro manuale per configurare i mock perché non genera codice. Questo non rappresenta molto lavoro per un progetto esistente poiché i prototipi non cambieranno molto: una volta che hai i tuoi mock, non avrai bisogno di cambiarli per un po '(questo è il mio caso). La tipizzazione aggiuntiva fornisce il controllo completo dei mock. Se c'è qualcosa che non ti piace, cambi semplicemente la tua finta.

Non c'è bisogno di un corridore di prova speciale. Hai solo bisogno di creare una serie di test e passarla a una funzione run_tests. Un po 'più di lavoro manuale anche qui, ma mi piace decisamente l'idea di un quadro autonomo autonomo.

Inoltre contiene alcuni trucchi C che non conoscevo.

Nel complesso Cmockery ha bisogno di capire meglio i mock per iniziare. Gli esempi dovrebbero aiutarti a superare questo. Sembra che possa fare il lavoro con una meccanica più semplice.

20
Philippe A.

Come novellino di C, ho trovato le diapositive chiamate Sviluppo guidato dal test in C molto utile. Fondamentalmente, usa lo standard assert() insieme a && per consegnare un messaggio, senza alcuna dipendenza esterna. Se qualcuno è abituato a un framework di testing completo, questo probabilmente non lo farà :)

15
chelmertz

Non utilizzo un framework, utilizzo solo gli autotools "verifica" il supporto di destinazione. Implementare un "principale" e utilizzare assert (s).

Il mio test dir Makefile.am (s) assomiglia a:

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
12
navicore

C'è CUnit

E Embedded Unit è un framework di testing unitario per Embedded C System. Il suo design è stato copiato da JUnit e CUnit e altri, e quindi adattato in qualche modo per Embedded C System. L'unità incorporata non richiede le librerie C std. Tutti gli oggetti sono assegnati all'area const.

E Tessy automatizza la verifica dell'unità del software incorporato.

12
prakash

Abbiamo scritto CHEAT (ospitato su GitHub ) per una facile fruibilità e portabilità.

Non ha dipendenze e non richiede installazione o configurazione. Sono necessari solo un file di intestazione e un test case.

#include <cheat.h>

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

I test vengono compilati in un eseguibile che si occupa di eseguire i test e riportare i risultati.

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

Ha anche dei bei colori.

12
Tuplanolla

Il libro di Michael Feather "Lavorare efficacemente con il codice legacy" presenta molte tecniche specifiche per i test unitari durante lo sviluppo di C.

Ci sono tecniche relative all'iniezione di dipendenze specifiche per C che non ho visto da nessun'altra parte.

11

CppUTest - Quadro altamente raccomandato per il test del codice C dell'unità.

Gli esempi nel libro menzionato in questo thread TDD per C embedded sono scritti usando CppUTest.

7
ratkok

diverso dal mio pregiudizio evidente

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

è un bel modo semplice per testare il codice C. imita xUnit

6
Keith Nicholas

Io uso CxxTest per un ambiente c/c ++ incorporato (principalmente C++).

Preferisco CxxTest perché ha uno script Perl/python per creare il runner di test. Dopo una piccola pendenza per farlo configurare (ancora più piccolo dato che non è necessario scrivere il runner di test), è piuttosto facile da usare (include esempi e documentazione utile). La maggior parte del lavoro consisteva nell'impostare l '"hardware" al quale il codice accede, così che potevo testare in modo efficace unità/modulo. Dopodiché è facile aggiungere nuovi casi di test di unità.

Come accennato in precedenza, è un framework di test di unità C/C++. Quindi avrai bisogno di un compilatore C++.

CxxTest Guida dell'utenteCxxTest Wiki

6
Zing-

Dopo aver letto Minunit ho pensato che un modo migliore era basare il test in macro assert che uso molto come tecnica del programma difensivo. Quindi ho usato la stessa idea di Minunit mista a quella standard. Puoi vedere il mio framework (un buon nome potrebbe essere NoMinunit) in blog di k0ga

Google ha un eccellente framework di test. https://github.com/google/googletest/blob/master/googletest/docs/primer.md

E sì, per quello che vedo funzionerà con C semplice, cioè non richiede funzionalità C++ (potrebbe richiedere compilatore C++, non è sicuro).

4
Paweł Hajdan
4
Landon Kuhn

Cmockery è un progetto lanciato di recente che consiste in una libreria C molto semplice da usare per scrivere i test delle unità.

4

Per prima cosa, guarda qui: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C

La mia azienda ha una libreria C che i nostri clienti usano. Usiamo CxxTest (una libreria di test di unità C++) per testare il codice. CppUnit funzionerà anche. Se sei bloccato in C, ti consiglio RCUNIT (ma anche CUnit è buono).

3
Kevin
2
Tony Bai

API Sanity Checker - framework di test per librerie C/C++:

Un generatore automatico di test unitari di base per una libreria C/C++ condivisa. È in grado di generare dati di input ragionevoli (nella maggior parte, ma purtroppo non tutti) per i parametri e comporre casi di test semplici ("sanity" o "shallow") per ogni funzione nell'API attraverso l'analisi delle dichiarazioni nell'intestazione File.

La qualità dei test generati consente di verificare l'assenza di errori critici in casi d'uso semplici. Lo strumento è in grado di costruire ed eseguire test generati e rilevare arresti anomali (segfault), aborti, tutti i tipi di segnali emessi, codice di ritorno del programma diverso da zero e sospensione del programma.

Esempi:

2
linuxbuild

Ho usato RCUNIT per fare alcuni test unitari per codice incorporato su PC prima di testare il target. Una buona astrazione dell'interfaccia hardware è importante perché i registri mappati in memoria ti uccideranno.

2
Gerhard

Se hai familiarità con JUnit allora ti consiglio CppUnit. http://cppunit.sourceforge.net/cppunit-wiki

Questo presuppone che tu abbia un compilatore c ++ per fare i test unitari. se no, allora sono d'accordo con Adam Rosenfield che controllare è quello che vuoi.

2
Kwondri

LibU ( http://koanlogic.com/libu ) ha un modulo di test unitario che consente esplicite dipendenze tra suite di test/caso, isolamento del test, esecuzione parallela e un formattatore di report personalizzabile (i formati predefiniti sono xml e txt).

La libreria è dotata di licenza BSD e contiene molti altri moduli utili: reti, debug, strutture dati comunemente utilizzate, configurazione, ecc. - se ne hai bisogno nei tuoi progetti ...

1
bongo

Sono sorpreso che nessuno abbia menzionato Cutter (http://cutter.sourceforge.net/) Puoi testare C e C++, si integra perfettamente con gli autotools e ha a disposizione un tutorial davvero piacevole.

1
Kris

Una tecnica da utilizzare è lo sviluppo del codice di test unitario con un framework C++ xUnit (e un compilatore C++), mantenendo l'origine per il sistema di destinazione come moduli C.

Assicurati di compilare regolarmente la tua fonte C sotto il tuo cross-compilatore, automaticamente con i tuoi test di unità, se possibile.

1
quamrana

Se sei ancora alla ricerca di framework di test, CUnitWin32 è uno per la piattaforma Win32/NT.

Questo risolve un problema fondamentale che ho affrontato con altri framework di test. Vale a dire che le variabili globali/statiche sono in uno stato deterministico perché ogni test viene eseguito come processo separato.

0
Dushara

Nel caso tu stia bersagliando piattaforme Win32 o modalità kernel NT, dovresti dare un'occhiata a cfix .

0
Johannes Passing

Ho appena scritto Libcut per frustrazione con le librerie di test delle unità C esistenti. Ha un tipo automatico di stringhe di primitive (nessuna necessità di test_eq_int, test_eq_long, test_eq_short, ecc ...; solo due set diversi per primitive e stringhe) e consiste in un file di intestazione. Ecco un breve esempio:

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

Funziona solo con C11, però.

0
kirbyfan64sos