Iniziare con CppUTest
Uccello
14 mag 2017
1 min read

Conclusioni principali
CppUTest è un framework di testing leggero, attivamente mantenuto in stile xUnit per C/C++, con uno strato di integrazione C che funziona perfettamente anche in codebase pesantemente C.
Puoi installarlo tramite gestori di pacchetti (distro Linux, Homebrew) o clonare il repository GitHub.
Una configurazione minima consiste in:
una directory di produzione
src/,una directory di test
t/,un test runner (
CommandLineTestRunner), emoduli di test che utilizzano blocchi
TEST_GROUPeTEST().
CppUTest fornisce un aiuto MakefileWorker.mk che semplifica la costruzione dei test, il collegamento delle librerie e la gestione delle flag.
Rilevamento delle perdite di memoria è abilitato di default tramite override di malloc/free, catturando perdite all'interno del codice sorgente testato.
Copertura del codice tramite gcov si integra facilmente abilitando
CPPUTEST_USE_GCOV=Y, producendo report di copertura completi e riepiloghi HTML.Il framework include funzionalità avanzate: mocking, plugin, script di aiuto e interoperabilità diretta con C — utile per codebase aziendali complesse.
Q&A Highlights
Cos'è CppUTest e perché usarlo?
È un robusto framework di testing in stile xUnit per C/C++ con un'API pulita, macro assert integrate, rilevamento di perdite e sviluppo attivo — ideale per sistemi legacy o moderni.
Come si struttura un progetto di base utilizzando CppUTest?
src/ code/ code.cpp code.h main.cpp t/ main.cpp (test runner) test.cpp (test suite)
Come esegui tutti i test?
Il test runner utilizza:
return CommandLineTestRunner::RunAllTests(ac, av);
Come costruisci i test senza configurare manualmente le opzioni del compilatore?
Usa
MakefileWorker.mkdi CppUTest, che gestisce automaticamente flag, collegamento ed esecuzione dei test.CppUTest può rilevare automaticamente le perdite di memoria?
Sì. Esso sovrascrive malloc/free durante le build di test, riportando:
quale test ha causato il leak,
dove si è verificato,
dimensione del leak e contenuto della memoria.
Esempio di output di errore:
Memory leak(s) found. Allocated at: code.c line 6 Leak size: 1
Come genero code coverage?
Abilita:
CPPUTEST_USE_GCOV=YAssicurati che
filterGcov.shsia disponibile in$(CPPUTEST_HOME)/scripts/.Esegui: make
gcovQuesto produce
.gcov, testo riassuntivo e report di copertura HTML.
Cos'altro può fare CppUTest oltre al testing di base?
framework di mocking
sistema di plugin
script di automazione helper
integrazione C nativa
macro di asserzione estensive
Chi è il pubblico ideale per CppUTest?
Team che lavorano con sistemi embedded, piattaforme C, servizi C++, o qualsiasi ambiente dove l'affidabilità e la sicurezza della memoria devono essere continuamente convalidate.
At SparkPost, dedichiamo molto tempo ed energie al testing del nostro codice. La nostra piattaforma è scritta in C e recentemente ho studiato l'integrazione con un framework di unit test chiamato “CppUTest”, che fornisce test in stile xUnit per C/C++. Questo framework è robusto, ricco di funzionalità e in fase di sviluppo attivo, il che lo rende una scelta eccellente. Fornisce anche un layer di integrazione C che ha reso facile l'uso con il codice C della nostra piattaforma anche se la maggior parte del framework è in C++. Questo tutorial copre come iniziare a usare CppUTest nei tuoi progetti.
At SparkPost, dedichiamo molto tempo ed energie al testing del nostro codice. La nostra piattaforma è scritta in C e recentemente ho studiato l'integrazione con un framework di unit test chiamato “CppUTest”, che fornisce test in stile xUnit per C/C++. Questo framework è robusto, ricco di funzionalità e in fase di sviluppo attivo, il che lo rende una scelta eccellente. Fornisce anche un layer di integrazione C che ha reso facile l'uso con il codice C della nostra piattaforma anche se la maggior parte del framework è in C++. Questo tutorial copre come iniziare a usare CppUTest nei tuoi progetti.
At SparkPost, dedichiamo molto tempo ed energie al testing del nostro codice. La nostra piattaforma è scritta in C e recentemente ho studiato l'integrazione con un framework di unit test chiamato “CppUTest”, che fornisce test in stile xUnit per C/C++. Questo framework è robusto, ricco di funzionalità e in fase di sviluppo attivo, il che lo rende una scelta eccellente. Fornisce anche un layer di integrazione C che ha reso facile l'uso con il codice C della nostra piattaforma anche se la maggior parte del framework è in C++. Questo tutorial copre come iniziare a usare CppUTest nei tuoi progetti.
Interessato a More?
Questo è solo la punta dell'iceberg quando si tratta di tutte le funzionalità contenute in questo strumento. Oltre alle basi discusse qui, ha anche un framework di simulazione, un layer di integrazione diretta C, e un framework di plugin, per citarne alcuni significativi. Il repository contiene anche un'intera directory di script di supporto che possono aiutare ad automatizzare alcune delle parti di routine del lavoro con il framework.
Spero che le informazioni qui ti aiutino a migliorare la qualità del codice C/C++ con questo ottimo strumento!
Questo è solo la punta dell'iceberg quando si tratta di tutte le funzionalità contenute in questo strumento. Oltre alle basi discusse qui, ha anche un framework di simulazione, un layer di integrazione diretta C, e un framework di plugin, per citarne alcuni significativi. Il repository contiene anche un'intera directory di script di supporto che possono aiutare ad automatizzare alcune delle parti di routine del lavoro con il framework.
Spero che le informazioni qui ti aiutino a migliorare la qualità del codice C/C++ con questo ottimo strumento!
Questo è solo la punta dell'iceberg quando si tratta di tutte le funzionalità contenute in questo strumento. Oltre alle basi discusse qui, ha anche un framework di simulazione, un layer di integrazione diretta C, e un framework di plugin, per citarne alcuni significativi. Il repository contiene anche un'intera directory di script di supporto che possono aiutare ad automatizzare alcune delle parti di routine del lavoro con il framework.
Spero che le informazioni qui ti aiutino a migliorare la qualità del codice C/C++ con questo ottimo strumento!
Scaricando CppUTest
La pagina del progetto CppUTest è disponibile sul sito ufficiale, e il repository è su github. È anche incluso nei repository di gestione dei pacchetti per molte distribuzioni linux, così come homebrew su Mac OS. Gli esempi che seguono sono stati eseguiti su Mac OS X, ma sono derivati da codice scritto per Red Hat, il sistema operativo su cui gira la nostra piattaforma.
Le basi sono ben documentate sulla pagina principale di CppUTest. Procediamo rapidamente attraverso questi aspetti per arrivare ad alcune delle caratteristiche più interessanti.
La pagina del progetto CppUTest è disponibile sul sito ufficiale, e il repository è su github. È anche incluso nei repository di gestione dei pacchetti per molte distribuzioni linux, così come homebrew su Mac OS. Gli esempi che seguono sono stati eseguiti su Mac OS X, ma sono derivati da codice scritto per Red Hat, il sistema operativo su cui gira la nostra piattaforma.
Le basi sono ben documentate sulla pagina principale di CppUTest. Procediamo rapidamente attraverso questi aspetti per arrivare ad alcune delle caratteristiche più interessanti.
La pagina del progetto CppUTest è disponibile sul sito ufficiale, e il repository è su github. È anche incluso nei repository di gestione dei pacchetti per molte distribuzioni linux, così come homebrew su Mac OS. Gli esempi che seguono sono stati eseguiti su Mac OS X, ma sono derivati da codice scritto per Red Hat, il sistema operativo su cui gira la nostra piattaforma.
Le basi sono ben documentate sulla pagina principale di CppUTest. Procediamo rapidamente attraverso questi aspetti per arrivare ad alcune delle caratteristiche più interessanti.
Gettare le fondamenta
Prima di tutto, scriviamo un po' di codice!
Il nostro progetto di test avrà un file 'main' e includerà una libreria di utilità chiamata 'code'. La libreria fornirà una semplice funzione che restituisce 1 (per ora). I file saranno organizzati in questo modo:
├── src │ ├── code │ │ ├── code.cpp │ │ └── code.h │ └── main.cpp └── t ├── main.cpp └── test.cpp
Iniziamo scrivendo i file src/
// src/main.cpp #include <stdlib.h> #include <stdio.h> #include "code.h" int main(void) { test_func(); printf("hello world!\n"); exit(0); }
// src/code/code.cpp #include <stdlib.h> #include "code.h" int test_func() { return 1; }
// src/code/code.h #ifndef __code_h__ #define __code_h__ int test_func(); #endif
Ora, facciamo i test, che si troveranno nella directory t/. La prima cosa da fare è impostare un test runner che eseguirà i nostri file di test. Questa è anche la funzione 'main' che verrà eseguita una volta compilato tutto:
// t/main.cpp #include "CppUTest/CommandLineTestRunner.h" int main(int ac, char** av) { return CommandLineTestRunner::RunAllTests(ac, av); }
Ora possiamo scrivere il nostro primo modulo di test:
// t/test.cpp #include "CppUTest/TestHarness.h" #include "code.h" TEST_GROUP(AwesomeExamples) { }; TEST(AwesomeExamples, FirstExample) { int x = test_func(); CHECK_EQUAL(1, x); }
Successivamente, dobbiamo scrivere i makefile. Ne avremo bisogno di due: uno per i file del progetto sotto src/, e uno per i test.
Prima di tutto, scriviamo un po' di codice!
Il nostro progetto di test avrà un file 'main' e includerà una libreria di utilità chiamata 'code'. La libreria fornirà una semplice funzione che restituisce 1 (per ora). I file saranno organizzati in questo modo:
├── src │ ├── code │ │ ├── code.cpp │ │ └── code.h │ └── main.cpp └── t ├── main.cpp └── test.cpp
Iniziamo scrivendo i file src/
// src/main.cpp #include <stdlib.h> #include <stdio.h> #include "code.h" int main(void) { test_func(); printf("hello world!\n"); exit(0); }
// src/code/code.cpp #include <stdlib.h> #include "code.h" int test_func() { return 1; }
// src/code/code.h #ifndef __code_h__ #define __code_h__ int test_func(); #endif
Ora, facciamo i test, che si troveranno nella directory t/. La prima cosa da fare è impostare un test runner che eseguirà i nostri file di test. Questa è anche la funzione 'main' che verrà eseguita una volta compilato tutto:
// t/main.cpp #include "CppUTest/CommandLineTestRunner.h" int main(int ac, char** av) { return CommandLineTestRunner::RunAllTests(ac, av); }
Ora possiamo scrivere il nostro primo modulo di test:
// t/test.cpp #include "CppUTest/TestHarness.h" #include "code.h" TEST_GROUP(AwesomeExamples) { }; TEST(AwesomeExamples, FirstExample) { int x = test_func(); CHECK_EQUAL(1, x); }
Successivamente, dobbiamo scrivere i makefile. Ne avremo bisogno di due: uno per i file del progetto sotto src/, e uno per i test.
Prima di tutto, scriviamo un po' di codice!
Il nostro progetto di test avrà un file 'main' e includerà una libreria di utilità chiamata 'code'. La libreria fornirà una semplice funzione che restituisce 1 (per ora). I file saranno organizzati in questo modo:
├── src │ ├── code │ │ ├── code.cpp │ │ └── code.h │ └── main.cpp └── t ├── main.cpp └── test.cpp
Iniziamo scrivendo i file src/
// src/main.cpp #include <stdlib.h> #include <stdio.h> #include "code.h" int main(void) { test_func(); printf("hello world!\n"); exit(0); }
// src/code/code.cpp #include <stdlib.h> #include "code.h" int test_func() { return 1; }
// src/code/code.h #ifndef __code_h__ #define __code_h__ int test_func(); #endif
Ora, facciamo i test, che si troveranno nella directory t/. La prima cosa da fare è impostare un test runner che eseguirà i nostri file di test. Questa è anche la funzione 'main' che verrà eseguita una volta compilato tutto:
// t/main.cpp #include "CppUTest/CommandLineTestRunner.h" int main(int ac, char** av) { return CommandLineTestRunner::RunAllTests(ac, av); }
Ora possiamo scrivere il nostro primo modulo di test:
// t/test.cpp #include "CppUTest/TestHarness.h" #include "code.h" TEST_GROUP(AwesomeExamples) { }; TEST(AwesomeExamples, FirstExample) { int x = test_func(); CHECK_EQUAL(1, x); }
Successivamente, dobbiamo scrivere i makefile. Ne avremo bisogno di due: uno per i file del progetto sotto src/, e uno per i test.
Project Makefile
Il makefile del progetto sarà allo stesso livello delle directory ‘src’ e ‘t’ alla radice del progetto. Dovrebbe apparire così:
# Makefile SRC_DIR = ./src CODE_DIR = $(SRC_DIR)/code OUT = example TEST_DIR = t test: make -C $(TEST_DIR) test_clean: make -C $(TEST_DIR) clean code.o: gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o main: code.o gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT) all: test main clean: test_clean rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)
Nota che questo utilizza ‘make -C’ per i target di test, il che significa che chiamerà di nuovo ‘make’ utilizzando il makefile nella directory di test.
A questo punto possiamo compilare il codice ‘src’ con il makefile e verificare che funzioni:
[]$ make main gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example []$ ./example hello world
Il makefile del progetto sarà allo stesso livello delle directory ‘src’ e ‘t’ alla radice del progetto. Dovrebbe apparire così:
# Makefile SRC_DIR = ./src CODE_DIR = $(SRC_DIR)/code OUT = example TEST_DIR = t test: make -C $(TEST_DIR) test_clean: make -C $(TEST_DIR) clean code.o: gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o main: code.o gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT) all: test main clean: test_clean rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)
Nota che questo utilizza ‘make -C’ per i target di test, il che significa che chiamerà di nuovo ‘make’ utilizzando il makefile nella directory di test.
A questo punto possiamo compilare il codice ‘src’ con il makefile e verificare che funzioni:
[]$ make main gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example []$ ./example hello world
Il makefile del progetto sarà allo stesso livello delle directory ‘src’ e ‘t’ alla radice del progetto. Dovrebbe apparire così:
# Makefile SRC_DIR = ./src CODE_DIR = $(SRC_DIR)/code OUT = example TEST_DIR = t test: make -C $(TEST_DIR) test_clean: make -C $(TEST_DIR) clean code.o: gcc -c -I$(CODE_DIR) $(CODE_DIR)/code.cpp -o $(CODE_DIR)/code.o main: code.o gcc -I$(CODE_DIR) $(CODE_DIR)/code.o $(SRC_DIR)/main.cpp -o $(OUT) all: test main clean: test_clean rm $(SRC_DIR)/*.o $(CODE_DIR)/*.o $(OUT)
Nota che questo utilizza ‘make -C’ per i target di test, il che significa che chiamerà di nuovo ‘make’ utilizzando il makefile nella directory di test.
A questo punto possiamo compilare il codice ‘src’ con il makefile e verificare che funzioni:
[]$ make main gcc -c -I./src/code ./src/code/code.cpp -o ./src/code/code.o gcc -I./src/code ./src/code/code.o ./src/main.cpp -o example []$ ./example hello world
Tests Makefile
Per i test, le cose sono un po' più complicate poiché dobbiamo caricare e integrare correttamente con la libreria CppUTest.
Il repository CppUTest fornisce un file chiamato “MakefileWorker.mk”. Offre molta funzionalità che rende la costruzione con CppUTest semplice. Il file si trova nella directory ‘build’ nel repository git. Per questo tutorial, supponiamo che sia stato copiato nella directory ‘t/’. Può essere utilizzato come segue:
# we don’t want to use relative paths, so we set these variables PROJECT_DIR=/path/to/project SRC_DIR=$(PROJECT_DIR)/src TEST_DIR=$(PROJECT_DIR)/t # specify where the source code and includes are located INCLUDE_DIRS=$(SRC_DIR)/code SRC_DIRS=$(SRC_DIR)/code # specify where the test code is located TEST_SRC_DIRS=$(TEST_DIR) # what to call the test binary TEST_TARGET=example # where the cpputest library is located CPPUTEST_HOME=/usr/local # run MakefileWorker.mk with the variables defined here include MakefileWorker.mk
Nota che CPPUTEST_HOME deve essere impostato su dove CppUTest è stato installato. Se hai installato un pacchetto distro, sarà tipicamente sotto /usr/local su un sistema linux/mac. Se hai controllato il repository da solo, è ovunque quel checkout sia.
Queste opzioni sono tutte documentate in MakefileWorker.mk.
MakefileWorker.mk aggiunge anche alcuni target del makefile, inclusi i seguenti:
all – costruisce i test indicati dal makefile
clean – rimuove tutti gli oggetti e i file gcov generati per i test
realclean – rimuove qualsiasi oggetto o file gcov nell'intero albero delle directory
flags – elenca tutte le flag configurate utilizzate per compilare i test
debug – elenca tutti i file sorgenti, oggetti, dipendenze e ‘cose da pulire’
Per i test, le cose sono un po' più complicate poiché dobbiamo caricare e integrare correttamente con la libreria CppUTest.
Il repository CppUTest fornisce un file chiamato “MakefileWorker.mk”. Offre molta funzionalità che rende la costruzione con CppUTest semplice. Il file si trova nella directory ‘build’ nel repository git. Per questo tutorial, supponiamo che sia stato copiato nella directory ‘t/’. Può essere utilizzato come segue:
# we don’t want to use relative paths, so we set these variables PROJECT_DIR=/path/to/project SRC_DIR=$(PROJECT_DIR)/src TEST_DIR=$(PROJECT_DIR)/t # specify where the source code and includes are located INCLUDE_DIRS=$(SRC_DIR)/code SRC_DIRS=$(SRC_DIR)/code # specify where the test code is located TEST_SRC_DIRS=$(TEST_DIR) # what to call the test binary TEST_TARGET=example # where the cpputest library is located CPPUTEST_HOME=/usr/local # run MakefileWorker.mk with the variables defined here include MakefileWorker.mk
Nota che CPPUTEST_HOME deve essere impostato su dove CppUTest è stato installato. Se hai installato un pacchetto distro, sarà tipicamente sotto /usr/local su un sistema linux/mac. Se hai controllato il repository da solo, è ovunque quel checkout sia.
Queste opzioni sono tutte documentate in MakefileWorker.mk.
MakefileWorker.mk aggiunge anche alcuni target del makefile, inclusi i seguenti:
all – costruisce i test indicati dal makefile
clean – rimuove tutti gli oggetti e i file gcov generati per i test
realclean – rimuove qualsiasi oggetto o file gcov nell'intero albero delle directory
flags – elenca tutte le flag configurate utilizzate per compilare i test
debug – elenca tutti i file sorgenti, oggetti, dipendenze e ‘cose da pulire’
Per i test, le cose sono un po' più complicate poiché dobbiamo caricare e integrare correttamente con la libreria CppUTest.
Il repository CppUTest fornisce un file chiamato “MakefileWorker.mk”. Offre molta funzionalità che rende la costruzione con CppUTest semplice. Il file si trova nella directory ‘build’ nel repository git. Per questo tutorial, supponiamo che sia stato copiato nella directory ‘t/’. Può essere utilizzato come segue:
# we don’t want to use relative paths, so we set these variables PROJECT_DIR=/path/to/project SRC_DIR=$(PROJECT_DIR)/src TEST_DIR=$(PROJECT_DIR)/t # specify where the source code and includes are located INCLUDE_DIRS=$(SRC_DIR)/code SRC_DIRS=$(SRC_DIR)/code # specify where the test code is located TEST_SRC_DIRS=$(TEST_DIR) # what to call the test binary TEST_TARGET=example # where the cpputest library is located CPPUTEST_HOME=/usr/local # run MakefileWorker.mk with the variables defined here include MakefileWorker.mk
Nota che CPPUTEST_HOME deve essere impostato su dove CppUTest è stato installato. Se hai installato un pacchetto distro, sarà tipicamente sotto /usr/local su un sistema linux/mac. Se hai controllato il repository da solo, è ovunque quel checkout sia.
Queste opzioni sono tutte documentate in MakefileWorker.mk.
MakefileWorker.mk aggiunge anche alcuni target del makefile, inclusi i seguenti:
all – costruisce i test indicati dal makefile
clean – rimuove tutti gli oggetti e i file gcov generati per i test
realclean – rimuove qualsiasi oggetto o file gcov nell'intero albero delle directory
flags – elenca tutte le flag configurate utilizzate per compilare i test
debug – elenca tutti i file sorgenti, oggetti, dipendenze e ‘cose da pulire’
Copertura del Codice
Il test unitario non sarebbe completo senza un report di copertura. Lo strumento di riferimento per questo per i progetti che utilizzano gcc è gcov, disponibile come parte della suite standard di utility gcc. Cpputest si integra facilmente con gcov, tutto ciò che devi fare è aggiungere questa riga al makefile:
CPPUTEST_USE_GCOV=Y
Successivamente, dobbiamo assicurarci che lo script filterGcov.sh da questo repository sia in ‘/scripts/filterGcov.sh’ rispetto a dove imposti ‘CPPUTEST_HOME’. Deve anche avere permessi di esecuzione.
Nel Makefile di esempio, sarebbe distribuito in ‘/usr/local/scripts/filterGcov.sh’. Se stai eseguendo CppUTest da un checkout del repo, tutto dovrebbe funzionare senza modifiche.
Con questo in atto, puoi semplicemente eseguire ‘make gcov’ e l'analisi verrà generata per te. Nel nostro caso dovremo ‘make -B’ per ricostruire i file oggetto con gcov abilitato:
[]$ make -B gcov < compilation output > for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \ FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \ gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \ done for f in ; do \ gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \ done /usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt cat gcov_report.txt 100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp mkdir -p gcov mv *.gcov gcov mv gcov_* gcov See gcov directory for details
Questo produrrà un certo numero di file in una nuova directory ‘gcov’. Questi sono:
code.cpp.gcov – il file ‘gcov’ effettivo per il codice testato
gcov_error.txt – un report di errori (nel nostro caso, dovrebbe essere vuoto)
gcov_output.txt – l'output effettivo del comando gcov eseguito
gcov_report.txt – un riassunto della copertura per ciascun file sotto test
gcov_report.txt.html – una versione html di gcov_report
Il test unitario non sarebbe completo senza un report di copertura. Lo strumento di riferimento per questo per i progetti che utilizzano gcc è gcov, disponibile come parte della suite standard di utility gcc. Cpputest si integra facilmente con gcov, tutto ciò che devi fare è aggiungere questa riga al makefile:
CPPUTEST_USE_GCOV=Y
Successivamente, dobbiamo assicurarci che lo script filterGcov.sh da questo repository sia in ‘/scripts/filterGcov.sh’ rispetto a dove imposti ‘CPPUTEST_HOME’. Deve anche avere permessi di esecuzione.
Nel Makefile di esempio, sarebbe distribuito in ‘/usr/local/scripts/filterGcov.sh’. Se stai eseguendo CppUTest da un checkout del repo, tutto dovrebbe funzionare senza modifiche.
Con questo in atto, puoi semplicemente eseguire ‘make gcov’ e l'analisi verrà generata per te. Nel nostro caso dovremo ‘make -B’ per ricostruire i file oggetto con gcov abilitato:
[]$ make -B gcov < compilation output > for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \ FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \ gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \ done for f in ; do \ gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \ done /usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt cat gcov_report.txt 100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp mkdir -p gcov mv *.gcov gcov mv gcov_* gcov See gcov directory for details
Questo produrrà un certo numero di file in una nuova directory ‘gcov’. Questi sono:
code.cpp.gcov – il file ‘gcov’ effettivo per il codice testato
gcov_error.txt – un report di errori (nel nostro caso, dovrebbe essere vuoto)
gcov_output.txt – l'output effettivo del comando gcov eseguito
gcov_report.txt – un riassunto della copertura per ciascun file sotto test
gcov_report.txt.html – una versione html di gcov_report
Il test unitario non sarebbe completo senza un report di copertura. Lo strumento di riferimento per questo per i progetti che utilizzano gcc è gcov, disponibile come parte della suite standard di utility gcc. Cpputest si integra facilmente con gcov, tutto ciò che devi fare è aggiungere questa riga al makefile:
CPPUTEST_USE_GCOV=Y
Successivamente, dobbiamo assicurarci che lo script filterGcov.sh da questo repository sia in ‘/scripts/filterGcov.sh’ rispetto a dove imposti ‘CPPUTEST_HOME’. Deve anche avere permessi di esecuzione.
Nel Makefile di esempio, sarebbe distribuito in ‘/usr/local/scripts/filterGcov.sh’. Se stai eseguendo CppUTest da un checkout del repo, tutto dovrebbe funzionare senza modifiche.
Con questo in atto, puoi semplicemente eseguire ‘make gcov’ e l'analisi verrà generata per te. Nel nostro caso dovremo ‘make -B’ per ricostruire i file oggetto con gcov abilitato:
[]$ make -B gcov < compilation output > for d in /Users/ykuperman/code/blogpost/qa/src/code ; do \ FILES=`ls $d/*.c $d/*.cc $d/*.cpp 2> /dev/null` ; \ gcov --object-directory objs/$d $FILES >> gcov_output.txt 2>>gcov_error.txt ; \ done for f in ; do \ gcov --object-directory objs/$f $f >> gcov_output.txt 2>>gcov_error.txt ; \ done /usr/local/scripts/filterGcov.sh gcov_output.txt gcov_error.txt gcov_report.txt example.txt cat gcov_report.txt 100.00% /Users/ykuperman/code/blogpost/qa/src/code/code.cpp mkdir -p gcov mv *.gcov gcov mv gcov_* gcov See gcov directory for details
Questo produrrà un certo numero di file in una nuova directory ‘gcov’. Questi sono:
code.cpp.gcov – il file ‘gcov’ effettivo per il codice testato
gcov_error.txt – un report di errori (nel nostro caso, dovrebbe essere vuoto)
gcov_output.txt – l'output effettivo del comando gcov eseguito
gcov_report.txt – un riassunto della copertura per ciascun file sotto test
gcov_report.txt.html – una versione html di gcov_report
Cpputest Memory Leak Detection
Cpputest ti permette di rilevare automaticamente la memoria persa ridefinendo la famiglia standard di funzioni "malloc/free" per utilizzare invece i propri wrapper. Questo consente di individuare rapidamente le perdite e riportarle per ogni esecuzione del test. È abilitato di default in MakefileWorker.mk, quindi è già attivo con i passaggi delineati finora.
Per illustrare, facciamo perdere un po' di memoria in test_func() !
Ritornando a code.c, aggiungiamo un malloc() alla funzione, come segue:
int test_func() { malloc(1); return 1; }
Ora, dopo la ricompilazione, viene prodotto il seguente errore:
test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample) Memory leak(s) found. Alloc num (4) Leak size: 1 Allocated at: ./code.c and line: 6 Type: "malloc" Memory: <
Questo mostra quale test ha causato la perdita, dove si è verificata nel codice sorgente e cosa c'era nella memoria persa. Molto utile!
Ci sono alcune avvertenze con questa funzionalità:
Cpputest utilizza macro del preprocessore per ridefinire dinamicamente tutte le chiamate alle funzioni standard di gestione della memoria. Ciò significa che funzionerà solo per le chiamate nel codice sorgente sotto test, dato che è quello che viene compilato con gli override di CppUTest. Le perdite nelle librerie collegate non verranno rilevate.
A volte la memoria che viene allocata per tutta la durata del processo non è destinata ad essere liberata. Questo può generare molti errori di spam se stai testando un modulo con questo comportamento. Per disabilitare il rilevamento delle perdite, puoi fare questo:
CPPUTEST_USE_MEM_LEAK_DETECTION=N
Cpputest ti permette di rilevare automaticamente la memoria persa ridefinendo la famiglia standard di funzioni "malloc/free" per utilizzare invece i propri wrapper. Questo consente di individuare rapidamente le perdite e riportarle per ogni esecuzione del test. È abilitato di default in MakefileWorker.mk, quindi è già attivo con i passaggi delineati finora.
Per illustrare, facciamo perdere un po' di memoria in test_func() !
Ritornando a code.c, aggiungiamo un malloc() alla funzione, come segue:
int test_func() { malloc(1); return 1; }
Ora, dopo la ricompilazione, viene prodotto il seguente errore:
test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample) Memory leak(s) found. Alloc num (4) Leak size: 1 Allocated at: ./code.c and line: 6 Type: "malloc" Memory: <
Questo mostra quale test ha causato la perdita, dove si è verificata nel codice sorgente e cosa c'era nella memoria persa. Molto utile!
Ci sono alcune avvertenze con questa funzionalità:
Cpputest utilizza macro del preprocessore per ridefinire dinamicamente tutte le chiamate alle funzioni standard di gestione della memoria. Ciò significa che funzionerà solo per le chiamate nel codice sorgente sotto test, dato che è quello che viene compilato con gli override di CppUTest. Le perdite nelle librerie collegate non verranno rilevate.
A volte la memoria che viene allocata per tutta la durata del processo non è destinata ad essere liberata. Questo può generare molti errori di spam se stai testando un modulo con questo comportamento. Per disabilitare il rilevamento delle perdite, puoi fare questo:
CPPUTEST_USE_MEM_LEAK_DETECTION=N
Cpputest ti permette di rilevare automaticamente la memoria persa ridefinendo la famiglia standard di funzioni "malloc/free" per utilizzare invece i propri wrapper. Questo consente di individuare rapidamente le perdite e riportarle per ogni esecuzione del test. È abilitato di default in MakefileWorker.mk, quindi è già attivo con i passaggi delineati finora.
Per illustrare, facciamo perdere un po' di memoria in test_func() !
Ritornando a code.c, aggiungiamo un malloc() alla funzione, come segue:
int test_func() { malloc(1); return 1; }
Ora, dopo la ricompilazione, viene prodotto il seguente errore:
test.cpp:9: error: Failure in TEST(AwesomeExamples, FirstExample) Memory leak(s) found. Alloc num (4) Leak size: 1 Allocated at: ./code.c and line: 6 Type: "malloc" Memory: <
Questo mostra quale test ha causato la perdita, dove si è verificata nel codice sorgente e cosa c'era nella memoria persa. Molto utile!
Ci sono alcune avvertenze con questa funzionalità:
Cpputest utilizza macro del preprocessore per ridefinire dinamicamente tutte le chiamate alle funzioni standard di gestione della memoria. Ciò significa che funzionerà solo per le chiamate nel codice sorgente sotto test, dato che è quello che viene compilato con gli override di CppUTest. Le perdite nelle librerie collegate non verranno rilevate.
A volte la memoria che viene allocata per tutta la durata del processo non è destinata ad essere liberata. Questo può generare molti errori di spam se stai testando un modulo con questo comportamento. Per disabilitare il rilevamento delle perdite, puoi fare questo:
CPPUTEST_USE_MEM_LEAK_DETECTION=N



