Domanda

Quest'estate ho lavorato su un sistema embedded scritto direttamente in C.Era un progetto esistente che l'azienda per cui lavoro aveva ripreso.Mi sono abbastanza abituato a scrivere unit test in Java utilizzando JUnit, ma non sapevo quale fosse il modo migliore per scrivere unit test per il codice esistente (che necessitava di refactoring) e per il nuovo codice aggiunto al sistema.

Esiste un modo per rendere il test unitario del codice C semplice semplice come il test unitario del codice Java con, ad esempio, JUnit?Qualsiasi intuizione che si applichi specificamente allo sviluppo integrato (compilazione incrociata sulla piattaforma arm-linux) sarebbe molto apprezzata.

È stato utile?

Soluzione

Un framework di test unitario in C è Controllo;è possibile trovare un elenco di framework di test unitari in C Qui ed è riprodotta di seguito.A seconda di quante funzioni della libreria standard ha il tuo runtime, potresti essere in grado o meno di utilizzarne una.

AceUnit

AceUnit (Advanced C and Embedded Unit) si presenta come un comodo framework di unit test del codice C.Cerca di imitare JUnit 4.x e include funzionalità simili alla riflessione.AceUnit può essere utilizzato in ambienti con vincoli di risorse, ad es.sviluppo di software incorporato e, cosa importante, 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 Windows.Non utilizza fork per intrappolare i segnali, sebbene gli autori abbiano espresso interesse ad aggiungere tale funzionalità.Vedi il Homepage di AceUnit.

Unità automatica GNU

Più o meno sulla stessa linea di Check, incluso il fork per eseguire unit test in uno spazio di indirizzi separato (in effetti, l'autore originale di Check ha preso in prestito l'idea da GNU Autounit).GNU Autounit utilizza ampiamente GLib, il che significa che il collegamento e simili richiedono opzioni speciali, ma questo potrebbe non essere un grosso problema per te, soprattutto se stai già utilizzando GTK o GLib.Vedi il Home page di GNU Autounit.

cUnità

Utilizza anche GLib, ma non esegue il fork per proteggere lo spazio degli indirizzi degli unit test.

Unità CU

Standard C, con piani per un'implementazione GUI Win32.Attualmente non esegue il fork o protegge in altro modo lo spazio degli indirizzi dei test unitari.In fase di sviluppo iniziale.Vedi il Home page di CUnit.

CuTest

Un framework semplice con un solo file .c e un file .h che inserisci nell'albero dei sorgenti.Vedi il Home page di CuTest.

Unità Cpp

Il principale framework di unit test per C++;puoi anche usarlo per testare il codice C.È stabile, sviluppato attivamente e dispone di un'interfaccia GUI.I motivi principali per non utilizzare CppUnit per C sono in primo luogo che è piuttosto grande e in secondo luogo è necessario scrivere i test in C++, il che significa che è necessario un compilatore C++.Se queste non sembrano preoccupazioni, vale sicuramente la pena prenderle in considerazione, insieme ad altri framework di unit test C++.Vedi il Homepage della CppUnit.

embUnit

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

Unità Min

Un set minimo di macro e il gioco è fatto!Il punto è mostrare quanto sia facile testare l'unità del tuo codice.Vedi il Home page di MinUnit.

Unità CU per Mr.Andò

Un'implementazione CUnit abbastanza nuova e apparentemente ancora in fase di sviluppo iniziale.Vedi il Unità CU per Mr.Home page di Ando.

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

Altri framework:

CMocka

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

Vedere la home page di CMocka.

Criterio

Criterion è un framework di unit test C multipiattaforma che supporta la registrazione automatica dei test, test parametrizzati, teorie e che può essere restituito in più formati, inclusi TAP e JUnit XML.Ogni test viene eseguito secondo un proprio processo, quindi segnali e arresti anomali possono essere segnalati o testati, se necessario.

Vedi il Home page del criterio per maggiori informazioni.

MAHUT

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

Vedere la home page dell'HWUT.

CVerde

Un framework di unit test e mocking moderno, portatile e multilingue per C e C++.Offre una notazione BDD opzionale, una libreria mocking, la possibilità di eseguirla in un singolo processo (per rendere più semplice il debug).È disponibile un test runner che rileva automaticamente le funzioni di test.Ma puoi crearne uno tuo a livello di codice.

Tutte queste funzionalità (e altro ancora) sono spiegate in il manuale CGreen.

Wikipedia fornisce un elenco dettagliato dei framework di unit test C sotto Elenco dei framework di unit testing:C

Altri suggerimenti

Personalmente mi piace il Quadro di prova di Google.

La vera difficoltà nel testare il codice C è rompere le dipendenze sui moduli esterni in modo da poter isolare il codice in unità.Ciò può essere particolarmente problematico quando si tenta di eseguire test sul codice legacy.In questo caso mi ritrovo spesso ad utilizzare il linker per utilizzare le funzioni stub nei test.

Questo è ciò a cui si riferiscono le persone quando parlano di "cuciture".In C la tua unica opzione è utilizzare il preprocessore o il linker per deridere le tue dipendenze.

Una tipica suite di test in uno dei miei progetti C potrebbe assomigliare 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));
}

Tieni presente che in realtà stai includendo il file C e non il file di intestazione.Ciò offre il vantaggio di accedere a tutti i membri dati statici.Qui prendo in giro il mio logger (che potrebbe essere in logger.o e fornisco un'implementazione vuota.Ciò significa che il file di test viene compilato e collegato in modo indipendente dal resto della base di codice ed eseguito in modo isolato.

Per quanto riguarda la compilazione incrociata del codice, affinché funzioni sono necessarie buone funzionalità sul target.L'ho fatto con googletest compilato in modo incrociato su Linux su un'architettura PowerPC.Questo ha senso perché lì hai una shell completa e un sistema operativo per raccogliere i risultati.Per ambienti meno ricchi (che classifico come qualsiasi cosa senza un sistema operativo completo) dovresti semplicemente 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 generalmente molto più semplice grazie al fatto che il codice OO è in generale molto meno accoppiato rispetto a quello procedurale (ovviamente questo dipende molto dallo stile di codifica).Anche in C++ è possibile utilizzare trucchi come l'inserimento delle dipendenze e l'override del metodo per inserire giunture nel codice che altrimenti sarebbe incapsulato.

Michael Feathers ha un ottimo libro sul test del codice legacy.In un capitolo tratta le tecniche per gestire il codice non OO che consiglio vivamente.

Modificare:Ho scritto un post sul blog sul codice procedurale dei test unitari, con fonte disponibile su GitHub.

Modificare:C'è un nuovo libro in uscita da Pragmatic Programmers che affronta specificamente il codice C di test unitario che Consiglio vivamente.

Unità minima è un framework di test unitario incredibilmente semplice.Lo sto usando per testare il codice del microcontrollore C per avr.

Attualmente sto utilizzando il framework di unit test CuTest:

http://cutest.sourceforge.net/

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

  • Un file di intestazione incluso ovunque si chiami le routine più carine
  • Un singolo file "C" aggiuntivo da compilare/collegare nell'immagine
  • Alcuni semplici codice aggiunti a Main per impostare e chiamare i test unitari: ho solo questo in una funzione principale () che viene compilata se unitest è definito durante la build.

Il sistema deve supportare un heap e alcune funzionalità stdio (che non tutti i sistemi embedded hanno).Ma il codice è abbastanza semplice da poter probabilmente lavorare con alternative a tali requisiti se la tua piattaforma non li dispone.

Con un uso giudizioso dei blocchi "C"{} esterni, supporta perfettamente anche il test del C++.

Dico quasi la stessa cosa di Ratkok ma se hai una svolta incorporata nei test unitari allora...

Unità - Framework altamente raccomandato per il test unitario del codice C.

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

Potresti anche voler dare un'occhiata a libtap, un framework di test C che produce il Test Anything Protocol (TAP) e quindi si integra bene con una varietà di strumenti disponibili per questa tecnologia.Viene utilizzato principalmente nel mondo dei linguaggi dinamici, 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();
}

Esiste un elegante framework di unit test per C con supporto per oggetti fittizi chiamati cmocka.Richiede solo la libreria C standard, funziona su una vasta gamma di piattaforme informatiche (incluse quelle embedded) e con diversi compilatori.

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

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

Un semplice test è simile al seguente:

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

IL API è completamente documentato e diversi esempi fanno parte del codice sorgente.

Per iniziare con cmocka dovresti leggere l'articolo su LWN.net: Test unitari con oggetti fittizi in C

cmocka 1.0 è stato rilasciato a febbraio 2015.

Non sono andato lontano testando un'applicazione C legacy prima di iniziare a cercare un modo per simulare le funzioni.Avevo un disperato bisogno di mock per isolare il file C che voglio testare dagli altri.Ho provato cmock e penso che lo adotterò.

Cmock analizza i file header e genera funzioni fittizie basate sui prototipi che trova.I mock ti permetteranno di testare un file C in perfetto isolamento.Tutto quello che dovrai fare è collegare il tuo file di test con i mock invece che con i tuoi file oggetto reali.

Un altro vantaggio di cmock è che convaliderà i parametri passati alle funzioni derise e ti consentirà 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, si chiamano funzioni per testare e verificare le asserzioni.

L'ultimo passaggio è generare un corridore per i tuoi test con Unity.Cmock è legato al framework di test unitario.Unity è facile da apprendere come qualsiasi altro framework di unit test.

Vale la pena provare e abbastanza facile da capire:

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

Aggiornamento 1

Un altro framework su cui sto indagando è Cmockery.

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

È un framework C puro che supporta test unitari e mocking.Non ha alcuna dipendenza da Ruby (contrariamente a Cmock) e ha pochissima dipendenza dalle librerie esterne.

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

Non c'è bisogno di un corridore di prova speciale.Devi solo creare un array di test e passarlo a una funzione run_tests.Anche qui un po' più di lavoro manuale, ma mi piace sicuramente l'idea di un framework autonomo e autonomo.

Inoltre contiene alcuni ingegnosi trucchi in C che non conoscevo.

Nel complesso, Cmockery ha bisogno di una maggiore comprensione dei mock per iniziare.Gli esempi dovrebbero aiutarti a superare questo problema.Sembra che possa fare il lavoro con una meccanica più semplice.

Essendo un principiante del C, ho trovato le diapositive chiamate Sviluppo guidato dai test in C molto utile.Fondamentalmente, utilizza lo standard assert() insieme a && per consegnare un messaggio, senza dipendenze esterne.Se qualcuno è abituato a un framework di test full stack, questo probabilmente non funzionerà :)

C'è Unità CU

E Unità incorporata è un framework di test unitario per il sistema Embedded C.Il suo design è stato copiato da JUnit e CUnit e altri, e poi adattato in qualche modo per Embedded C System.L'unità incorporata non richiede librerie C standard.Tutti gli oggetti vengono assegnati all'area const.

E Tessy automatizza il test unitario del software incorporato.

Non utilizzo un framework, utilizzo solo il supporto target "check" degli strumenti automatici.Implementare un "main" e utilizzare assert(s).

La mia directory di test 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

Abbiamo scritto IMBROGLIONE (ospitato su GitHub) per una facile utilizzabilità e portabilità.

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

#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 di riportarne i risultati.

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

Ha anche dei bei colori.

Il libro di Michael Feather "Working Effectively with Legacy Code" presenta molte tecniche specifiche per i test unitari durante lo sviluppo in C.

Esistono tecniche relative all'inserimento delle dipendenze specifiche di C che non ho visto da nessun'altra parte.

CppUTest - Framework altamente raccomandato per il test unitario del codice C.

Gli esempi nel libro menzionato in questo thread TDD per C integrato sono scritti utilizzando CppUTest.

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

Preferisco CxxTest perché ha uno script perl/python per creare il test runner.Dopo una piccola difficoltà per configurarlo (ancora più piccolo poiché non è necessario scrivere il test runner), è abbastanza facile da usare (include campioni e documentazione utile).La maggior parte del lavoro è stata l'impostazione dell'hardware a cui il codice accede in modo da poter testare l'unità/modulo in modo efficace.Successivamente è facile aggiungere nuovi casi di test unitari.

Come accennato in precedenza si tratta di un framework di unit test C/C++.Quindi avrai bisogno di un compilatore C++.

Guida per l'utente di CxxTest CxxTestWiki

a parte il mio evidente pregiudizio

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

è un modo semplice e carino per eseguire test unitari del codice C.imita xUnit

Dopo aver letto Minunit ho pensato che un modo migliore fosse basare il test su assert macro che utilizzo molto come la tecnica del programma difensivo.Quindi ho usato la stessa idea di Minunit mescolata con l'asserzione standard.Puoi vedere il mio framework (un buon nome potrebbe essere NoMinunit) in Il blog di k0ga

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

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

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

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

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

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

Ciò presuppone che tu abbia un compilatore C++ per eseguire i test unitari.in caso contrario, devo essere d'accordo con Adam Rosenfield sul fatto che l'assegno è ciò che desideri.

ero solito RCUNIT per eseguire alcuni test unitari per il codice incorporato sul PC prima di testarlo sul target.Una buona astrazione dell'interfaccia hardware è importante, altrimenti l'endianness e i registri mappati in memoria ti uccideranno.

Controllo di integrità dell'API — framework di test per librerie C/C++:

Un generatore automatico di unit test di base per una libreria C/C++ condivisa.È in grado di generare dati di input ragionevoli (nella maggior parte dei casi, ma sfortunatamente non in tutti) per i parametri e comporre casi di test semplici ("salute mentale" o qualità "superficiale") 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 creare ed eseguire test generati e rilevare arresti anomali (segfault), interruzioni, tutti i tipi di segnali emessi, codice di ritorno del programma diverso da zero e blocco del programma.

Esempi:

Una tecnica da utilizzare consiste nello sviluppare il codice dello unit test con un framework C++ xUnit (e un compilatore C++), mantenendo l'origine per il sistema di destinazione come moduli C.

Assicurati di compilare regolarmente il sorgente C sotto il cross-compiler, automaticamente con i tuoi unit test, se possibile.

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

La libreria ha la licenza BSD e contiene molti altri moduli utili: networking, debug, strutture dati di uso comune, configurazione, ecc.- se ne avessi bisogno nei tuoi progetti...

Sono sorpreso che nessuno ne abbia parlato Taglierina (http://cutter.sourceforge.net/)Puoi testare C e C++, si integra perfettamente con gli strumenti automatici e ha a disposizione un tutorial davvero carino.

Se stai prendendo di mira le piattaforme Win32 o la modalità kernel NT, dovresti dare un'occhiata a cfix.

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

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top