Iniziare con CppUTest

Uccello

14 mag 2017

Email

1 min read

Iniziare con CppUTest

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), e

      • moduli di test che utilizzano blocchi TEST_GROUP e TEST().

    • 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.mk di 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?

    1. Abilita: CPPUTEST_USE_GCOV=Y

    2. Assicurati che filterGcov.sh sia disponibile in $(CPPUTEST_HOME)/scripts/.

    3. Esegui: make gcov

      Questo 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:

  1. all – costruisce i test indicati dal makefile

  2. clean – rimuove tutti gli oggetti e i file gcov generati per i test

  3. realclean – rimuove qualsiasi oggetto o file gcov nell'intero albero delle directory

  4. flags – elenca tutte le flag configurate utilizzate per compilare i test

  5. 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:

  1. all – costruisce i test indicati dal makefile

  2. clean – rimuove tutti gli oggetti e i file gcov generati per i test

  3. realclean – rimuove qualsiasi oggetto o file gcov nell'intero albero delle directory

  4. flags – elenca tutte le flag configurate utilizzate per compilare i test

  5. 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:

  1. all – costruisce i test indicati dal makefile

  2. clean – rimuove tutti gli oggetti e i file gcov generati per i test

  3. realclean – rimuove qualsiasi oggetto o file gcov nell'intero albero delle directory

  4. flags – elenca tutte le flag configurate utilizzate per compilare i test

  5. 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:

  1. code.cpp.gcov – il file ‘gcov’ effettivo per il codice testato

  2. gcov_error.txt – un report di errori (nel nostro caso, dovrebbe essere vuoto)

  3. gcov_output.txt – l'output effettivo del comando gcov eseguito

  4. gcov_report.txt – un riassunto della copertura per ciascun file sotto test

  5. 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:

  1. code.cpp.gcov – il file ‘gcov’ effettivo per il codice testato

  2. gcov_error.txt – un report di errori (nel nostro caso, dovrebbe essere vuoto)

  3. gcov_output.txt – l'output effettivo del comando gcov eseguito

  4. gcov_report.txt – un riassunto della copertura per ciascun file sotto test

  5. 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:

  1. code.cpp.gcov – il file ‘gcov’ effettivo per il codice testato

  2. gcov_error.txt – un report di errori (nel nostro caso, dovrebbe essere vuoto)

  3. gcov_output.txt – l'output effettivo del comando gcov eseguito

  4. gcov_report.txt – un riassunto della copertura per ciascun file sotto test

  5. 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à:

  1. 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.

  2. 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à:

  1. 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.

  2. 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à:

  1. 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.

  2. 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

Altre notizie

Leggi di più da questa categoria

A person is standing at a desk while typing on a laptop.

La piattaforma nativa AI completa che si adatta al tuo business.

© 2025 Bird

A person is standing at a desk while typing on a laptop.

La piattaforma nativa AI completa che si adatta al tuo business.

© 2025 Bird