Introducción a CppUTest

Pájaro

14 may 2017

Correo electrónico

1 min read

Introducción a CppUTest

Puntos clave

    • CppUTest es un marco de pruebas ligero, mantenido activamente, estilo xUnit para C/C++, con una capa de integración C que funciona sin problemas incluso en bases de código pesadas en C.

    • Puede instalarlo a través de gestores de paquetes (distribuciones de Linux, Homebrew) o clonar el repositorio de GitHub.

    • Una configuración mínima consiste en:

      • un directorio de producción src/,

      • un directorio de pruebas t/,

      • un runner de pruebas (CommandLineTestRunner), y

      • módulos de prueba utilizando bloques TEST_GROUP y TEST().

    • CppUTest proporciona un ayudante MakefileWorker.mk que simplifica la construcción de pruebas, el enlace de bibliotecas y el manejo de flags.

    • La detección de fugas de memoria está habilitada de forma predeterminada a través de sobrescrituras de malloc/free, capturando fugas dentro del código fuente probado.

    • La cobertura de código a través de gcov se integra fácilmente habilitando CPPUTEST_USE_GCOV=Y, produciendo informes de cobertura completa y resúmenes en HTML.

    • El marco incluye características avanzadas: mocks, plugins, scripts de ayuda e interoperabilidad directa con C, útiles para complejas bases de código empresariales.

Destacados de Q&A

  • ¿Qué es CppUTest y por qué usarlo?

    Es un marco de pruebas robusto, de estilo xUnit, para C/C++ con una API limpia, macros de aserción integradas, detección de fugas y desarrollo activo, ideal para sistemas heredados o modernos.

  • ¿Cómo estructuras un proyecto básico usando CppUTest?

    src/
      code/
        code.cpp
        code.h
      main.cpp
    t/
      main.cpp (test runner)
      test.cpp (test suite)
  • ¿Cómo se ejecutan todas las pruebas?

    El test runner utiliza:

    return CommandLineTestRunner::RunAllTests(ac, av);
  • ¿Cómo se construyen pruebas sin configurar manualmente las opciones del compilador?

    Utiliza MakefileWorker.mk de CppUTest, que maneja las banderas, el enlace y la ejecución de pruebas automáticamente.

  • ¿Puede CppUTest detectar fugas de memoria automáticamente?

    Sí. Sobrescribe malloc/free durante las compilaciones de prueba, informando:

    • qué prueba tuvo fugas,

    • dónde ocurrió,

    • tamaño de la fuga y contenido de la memoria.

    Ejemplo de salida de fallo:

    Memory leak(s) found.
    Allocated at: code.c line 6
    Leak size: 1
  • ¿Cómo genero la cobertura de código?

    1. Habilitar: CPPUTEST_USE_GCOV=Y

    2. Asegúrese de que filterGcov.sh esté disponible en $(CPPUTEST_HOME)/scripts/.

    3. Ejecutar: make gcov

      Esto produce .gcov, texto resumen, y reportes de cobertura en HTML.

  • ¿Qué más puede hacer CppUTest más allá de las pruebas básicas?

    • marco de pruebas simuladas

    • sistema de complementos

    • scripts de automatización de ayuda

    • integración nativa de C

    • macros de aserción extensas

  • ¿Para quién es más adecuado CppUTest?

    Equipos que trabajan con sistemas empotrados, plataformas C, servicios de C++, o cualquier entorno donde la fiabilidad y la seguridad de memoria deben ser validadas continuamente.

En SparkPost, dedicamos mucho tiempo y esfuerzo a probar nuestro código. Nuestra plataforma está escrita en C, y recientemente investigué la integración con un marco de pruebas unitarias llamado “CppUTest”, que proporciona pruebas al estilo xUnit para C/C++. Este marco es sólido, rico en funciones y está en desarrollo activo, lo que lo convierte en una excelente opción. También proporciona una capa de integración en C que facilitó su uso con nuestro código en C de la plataforma, aunque la mayor parte del marco es C++. Este tutorial cubre cómo comenzar con CppUTest en tus propios proyectos.

En SparkPost, dedicamos mucho tiempo y esfuerzo a probar nuestro código. Nuestra plataforma está escrita en C, y recientemente investigué la integración con un marco de pruebas unitarias llamado “CppUTest”, que proporciona pruebas al estilo xUnit para C/C++. Este marco es sólido, rico en funciones y está en desarrollo activo, lo que lo convierte en una excelente opción. También proporciona una capa de integración en C que facilitó su uso con nuestro código en C de la plataforma, aunque la mayor parte del marco es C++. Este tutorial cubre cómo comenzar con CppUTest en tus propios proyectos.

En SparkPost, dedicamos mucho tiempo y esfuerzo a probar nuestro código. Nuestra plataforma está escrita en C, y recientemente investigué la integración con un marco de pruebas unitarias llamado “CppUTest”, que proporciona pruebas al estilo xUnit para C/C++. Este marco es sólido, rico en funciones y está en desarrollo activo, lo que lo convierte en una excelente opción. También proporciona una capa de integración en C que facilitó su uso con nuestro código en C de la plataforma, aunque la mayor parte del marco es C++. Este tutorial cubre cómo comenzar con CppUTest en tus propios proyectos.

¿Interesado en más?

Esto es solo la punta del iceberg cuando se trata de todas las características contenidas en esta herramienta. Además de lo básico discutido aquí, también tiene un marco de burla, una capa de integración directa con C y un marco de plugins, por nombrar algunos de los más importantes. El repositorio también contiene todo un directorio de scripts auxiliares que pueden ayudar a automatizar algunas de las partes rutinarias de trabajar con el marco.

¡Espero que la información aquí te ayude a mejorar la calidad de tu código C/C++ con esta gran herramienta!

Esto es solo la punta del iceberg cuando se trata de todas las características contenidas en esta herramienta. Además de lo básico discutido aquí, también tiene un marco de burla, una capa de integración directa con C y un marco de plugins, por nombrar algunos de los más importantes. El repositorio también contiene todo un directorio de scripts auxiliares que pueden ayudar a automatizar algunas de las partes rutinarias de trabajar con el marco.

¡Espero que la información aquí te ayude a mejorar la calidad de tu código C/C++ con esta gran herramienta!

Esto es solo la punta del iceberg cuando se trata de todas las características contenidas en esta herramienta. Además de lo básico discutido aquí, también tiene un marco de burla, una capa de integración directa con C y un marco de plugins, por nombrar algunos de los más importantes. El repositorio también contiene todo un directorio de scripts auxiliares que pueden ayudar a automatizar algunas de las partes rutinarias de trabajar con el marco.

¡Espero que la información aquí te ayude a mejorar la calidad de tu código C/C++ con esta gran herramienta!

Descargando CppUTest

La página del proyecto CppUTest está disponible en el sitio web oficial, y el repositorio está en github. También está incluido en los repositorios de gestión de paquetes para muchas distribuciones de Linux, así como en homebrew en Mac OS. Los ejemplos que siguen fueron ejecutados en Mac OS X, pero se derivan de código escrito para Red Hat, el sistema operativo en el que nuestra plataforma se ejecuta.

Los conceptos básicos están bien documentados en la página de inicio de CppUTest. Vamos a pasar por eso rápidamente y llegar a algunas de las características más interesantes.

La página del proyecto CppUTest está disponible en el sitio web oficial, y el repositorio está en github. También está incluido en los repositorios de gestión de paquetes para muchas distribuciones de Linux, así como en homebrew en Mac OS. Los ejemplos que siguen fueron ejecutados en Mac OS X, pero se derivan de código escrito para Red Hat, el sistema operativo en el que nuestra plataforma se ejecuta.

Los conceptos básicos están bien documentados en la página de inicio de CppUTest. Vamos a pasar por eso rápidamente y llegar a algunas de las características más interesantes.

La página del proyecto CppUTest está disponible en el sitio web oficial, y el repositorio está en github. También está incluido en los repositorios de gestión de paquetes para muchas distribuciones de Linux, así como en homebrew en Mac OS. Los ejemplos que siguen fueron ejecutados en Mac OS X, pero se derivan de código escrito para Red Hat, el sistema operativo en el que nuestra plataforma se ejecuta.

Los conceptos básicos están bien documentados en la página de inicio de CppUTest. Vamos a pasar por eso rápidamente y llegar a algunas de las características más interesantes.

Laying the Foundation

Lo primero es lo primero, ¡vamos a escribir algo de código!

Nuestro proyecto de prueba tendrá un archivo ‘main’ e incluirá una biblioteca de utilidades llamada ‘code’. La biblioteca proporcionará una función simple que devuelve 1 (por ahora). Los archivos estarán dispuestos de esta manera:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

Comencemos escribiendo los archivos de 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

Ahora, hagamos las pruebas, que vivirán en el directorio t/.  Lo primero que hay que hacer es configurar un corredor de pruebas que ejecutará nuestros archivos de prueba. Esta también es la función ‘main’ que se ejecutará una vez que todo esto esté compilado:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

Ahora podemos escribir nuestro primer módulo de prueba:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

Después, necesitamos escribir makefiles.  Necesitaremos dos: uno para los archivos del proyecto bajo src/, y otro para las pruebas.

Lo primero es lo primero, ¡vamos a escribir algo de código!

Nuestro proyecto de prueba tendrá un archivo ‘main’ e incluirá una biblioteca de utilidades llamada ‘code’. La biblioteca proporcionará una función simple que devuelve 1 (por ahora). Los archivos estarán dispuestos de esta manera:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

Comencemos escribiendo los archivos de 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

Ahora, hagamos las pruebas, que vivirán en el directorio t/.  Lo primero que hay que hacer es configurar un corredor de pruebas que ejecutará nuestros archivos de prueba. Esta también es la función ‘main’ que se ejecutará una vez que todo esto esté compilado:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

Ahora podemos escribir nuestro primer módulo de prueba:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

Después, necesitamos escribir makefiles.  Necesitaremos dos: uno para los archivos del proyecto bajo src/, y otro para las pruebas.

Lo primero es lo primero, ¡vamos a escribir algo de código!

Nuestro proyecto de prueba tendrá un archivo ‘main’ e incluirá una biblioteca de utilidades llamada ‘code’. La biblioteca proporcionará una función simple que devuelve 1 (por ahora). Los archivos estarán dispuestos de esta manera:

├── src
├── code
├── code.cpp
└── code.h
└── main.cpp
└── t
    ├── main.cpp
    └── test.cpp

Comencemos escribiendo los archivos de 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

Ahora, hagamos las pruebas, que vivirán en el directorio t/.  Lo primero que hay que hacer es configurar un corredor de pruebas que ejecutará nuestros archivos de prueba. Esta también es la función ‘main’ que se ejecutará una vez que todo esto esté compilado:

// t/main.cpp
#include "CppUTest/CommandLineTestRunner.h"
int main(int ac, char** av) {
return CommandLineTestRunner::RunAllTests(ac, av);
}

Ahora podemos escribir nuestro primer módulo de prueba:

// t/test.cpp
#include "CppUTest/TestHarness.h"
#include "code.h"
TEST_GROUP(AwesomeExamples)
{
};
TEST(AwesomeExamples, FirstExample)
{
    int x = test_func();
    CHECK_EQUAL(1, x);
}

Después, necesitamos escribir makefiles.  Necesitaremos dos: uno para los archivos del proyecto bajo src/, y otro para las pruebas.

Proyecto Makefile

El makefile del proyecto estará al mismo nivel que los directorios ‘src’ y ‘t’ en la raíz del proyecto. Debería verse así:

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

Note que este utiliza ‘make -C’  para los objetivos de prueba – lo que significa que llamará a ‘make’  de nuevo usando el makefile en el directorio de prueba.

En este punto podemos compilar el código ‘src’ con el makefile y ver que funciona:

[]$ 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

El makefile del proyecto estará al mismo nivel que los directorios ‘src’ y ‘t’ en la raíz del proyecto. Debería verse así:

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

Note que este utiliza ‘make -C’  para los objetivos de prueba – lo que significa que llamará a ‘make’  de nuevo usando el makefile en el directorio de prueba.

En este punto podemos compilar el código ‘src’ con el makefile y ver que funciona:

[]$ 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

El makefile del proyecto estará al mismo nivel que los directorios ‘src’ y ‘t’ en la raíz del proyecto. Debería verse así:

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

Note que este utiliza ‘make -C’  para los objetivos de prueba – lo que significa que llamará a ‘make’  de nuevo usando el makefile en el directorio de prueba.

En este punto podemos compilar el código ‘src’ con el makefile y ver que funciona:

[]$ 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

Para las pruebas, las cosas son un poco más complejas ya que necesitamos cargar e integrar adecuadamente con la biblioteca CppUTest.

El repositorio de CppUTest proporciona un archivo llamado “MakefileWorker.mk”. Proporciona mucha funcionalidad que hace que la construcción con CppUTest sea simple. El archivo se encuentra en el directorio “build” en el repositorio git. Para este tutorial vamos a asumir que ha sido copiado al directorio ‘t/’. Se puede utilizar de la siguiente manera:

# 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 que CPPUTEST_HOME debe establecerse en donde CppUTest fue instalado. Si has instalado un paquete de distribución, esto típicamente estará bajo /usr/local en un sistema linux/mac. Si has clonado el repositorio por tu cuenta, es donde esa clonación esté.

Todas estas opciones están documentadas en MakefileWorker.mk.

MakefileWorker.mk también añade algunos objetivos de makefile, incluyendo los siguientes:

  1. all – compila las pruebas indicadas por el makefile

  2. clean – elimina todos los archivos objeto y gcov generados para las pruebas

  3. realclean – elimina cualquier archivo objeto o gcov en todo el árbol de directorios

  4. flags – lista todas las banderas configuradas utilizadas para compilar las pruebas

  5. debug – lista todos los archivos fuente, objetos, dependencias y ‘cosas para limpiar’

Para las pruebas, las cosas son un poco más complejas ya que necesitamos cargar e integrar adecuadamente con la biblioteca CppUTest.

El repositorio de CppUTest proporciona un archivo llamado “MakefileWorker.mk”. Proporciona mucha funcionalidad que hace que la construcción con CppUTest sea simple. El archivo se encuentra en el directorio “build” en el repositorio git. Para este tutorial vamos a asumir que ha sido copiado al directorio ‘t/’. Se puede utilizar de la siguiente manera:

# 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 que CPPUTEST_HOME debe establecerse en donde CppUTest fue instalado. Si has instalado un paquete de distribución, esto típicamente estará bajo /usr/local en un sistema linux/mac. Si has clonado el repositorio por tu cuenta, es donde esa clonación esté.

Todas estas opciones están documentadas en MakefileWorker.mk.

MakefileWorker.mk también añade algunos objetivos de makefile, incluyendo los siguientes:

  1. all – compila las pruebas indicadas por el makefile

  2. clean – elimina todos los archivos objeto y gcov generados para las pruebas

  3. realclean – elimina cualquier archivo objeto o gcov en todo el árbol de directorios

  4. flags – lista todas las banderas configuradas utilizadas para compilar las pruebas

  5. debug – lista todos los archivos fuente, objetos, dependencias y ‘cosas para limpiar’

Para las pruebas, las cosas son un poco más complejas ya que necesitamos cargar e integrar adecuadamente con la biblioteca CppUTest.

El repositorio de CppUTest proporciona un archivo llamado “MakefileWorker.mk”. Proporciona mucha funcionalidad que hace que la construcción con CppUTest sea simple. El archivo se encuentra en el directorio “build” en el repositorio git. Para este tutorial vamos a asumir que ha sido copiado al directorio ‘t/’. Se puede utilizar de la siguiente manera:

# 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 que CPPUTEST_HOME debe establecerse en donde CppUTest fue instalado. Si has instalado un paquete de distribución, esto típicamente estará bajo /usr/local en un sistema linux/mac. Si has clonado el repositorio por tu cuenta, es donde esa clonación esté.

Todas estas opciones están documentadas en MakefileWorker.mk.

MakefileWorker.mk también añade algunos objetivos de makefile, incluyendo los siguientes:

  1. all – compila las pruebas indicadas por el makefile

  2. clean – elimina todos los archivos objeto y gcov generados para las pruebas

  3. realclean – elimina cualquier archivo objeto o gcov en todo el árbol de directorios

  4. flags – lista todas las banderas configuradas utilizadas para compilar las pruebas

  5. debug – lista todos los archivos fuente, objetos, dependencias y ‘cosas para limpiar’

Code Coverage

Las pruebas unitarias no estarían completas sin un informe de cobertura. La herramienta predilecta para esto en proyectos que usan gcc es gcov, disponible como parte del conjunto estándar de utilidades de gcc. Cpputest se integra fácilmente con gcov, todo lo que necesitas hacer es agregar esta línea al makefile:

CPPUTEST_USE_GCOV=Y

A continuación, necesitamos asegurarnos de que el script filterGcov.sh del este repositorio esté en ‘/scripts/filterGcov.sh’ relativo a donde sea que hayas establecido ‘CPPUTEST_HOME’. También necesita tener permisos de ejecución.

En el Makefile de ejemplo, se desplegaría en ‘/usr/local/scripts/filterGcov.sh’. Si estás ejecutando CppUTest desde una clonación del repositorio, todo debería funcionar sin modificaciones.

Con eso en su lugar, simplemente puedes ejecutar ‘make gcov’ y el análisis se generará para ti. En nuestro caso, necesitaremos usar ‘make -B’ para reconstruir los archivos objeto habilitados con gcov:

[]$ 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

Esto generará varios archivos en un nuevo directorio ‘gcov’. Estos son:

  1. code.cpp.gcov – el archivo ‘gcov’ real del código que se está probando

  2. gcov_error.txt – un informe de errores (en nuestro caso, debería estar vacío)

  3. gcov_output.txt – la salida real del comando gcov que se ejecutó

  4. gcov_report.txt – un resumen de la cobertura de cada archivo probado

  5. gcov_report.txt.html – una versión html de gcov_report

Las pruebas unitarias no estarían completas sin un informe de cobertura. La herramienta predilecta para esto en proyectos que usan gcc es gcov, disponible como parte del conjunto estándar de utilidades de gcc. Cpputest se integra fácilmente con gcov, todo lo que necesitas hacer es agregar esta línea al makefile:

CPPUTEST_USE_GCOV=Y

A continuación, necesitamos asegurarnos de que el script filterGcov.sh del este repositorio esté en ‘/scripts/filterGcov.sh’ relativo a donde sea que hayas establecido ‘CPPUTEST_HOME’. También necesita tener permisos de ejecución.

En el Makefile de ejemplo, se desplegaría en ‘/usr/local/scripts/filterGcov.sh’. Si estás ejecutando CppUTest desde una clonación del repositorio, todo debería funcionar sin modificaciones.

Con eso en su lugar, simplemente puedes ejecutar ‘make gcov’ y el análisis se generará para ti. En nuestro caso, necesitaremos usar ‘make -B’ para reconstruir los archivos objeto habilitados con gcov:

[]$ 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

Esto generará varios archivos en un nuevo directorio ‘gcov’. Estos son:

  1. code.cpp.gcov – el archivo ‘gcov’ real del código que se está probando

  2. gcov_error.txt – un informe de errores (en nuestro caso, debería estar vacío)

  3. gcov_output.txt – la salida real del comando gcov que se ejecutó

  4. gcov_report.txt – un resumen de la cobertura de cada archivo probado

  5. gcov_report.txt.html – una versión html de gcov_report

Las pruebas unitarias no estarían completas sin un informe de cobertura. La herramienta predilecta para esto en proyectos que usan gcc es gcov, disponible como parte del conjunto estándar de utilidades de gcc. Cpputest se integra fácilmente con gcov, todo lo que necesitas hacer es agregar esta línea al makefile:

CPPUTEST_USE_GCOV=Y

A continuación, necesitamos asegurarnos de que el script filterGcov.sh del este repositorio esté en ‘/scripts/filterGcov.sh’ relativo a donde sea que hayas establecido ‘CPPUTEST_HOME’. También necesita tener permisos de ejecución.

En el Makefile de ejemplo, se desplegaría en ‘/usr/local/scripts/filterGcov.sh’. Si estás ejecutando CppUTest desde una clonación del repositorio, todo debería funcionar sin modificaciones.

Con eso en su lugar, simplemente puedes ejecutar ‘make gcov’ y el análisis se generará para ti. En nuestro caso, necesitaremos usar ‘make -B’ para reconstruir los archivos objeto habilitados con gcov:

[]$ 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

Esto generará varios archivos en un nuevo directorio ‘gcov’. Estos son:

  1. code.cpp.gcov – el archivo ‘gcov’ real del código que se está probando

  2. gcov_error.txt – un informe de errores (en nuestro caso, debería estar vacío)

  3. gcov_output.txt – la salida real del comando gcov que se ejecutó

  4. gcov_report.txt – un resumen de la cobertura de cada archivo probado

  5. gcov_report.txt.html – una versión html de gcov_report

Cpputest Memory Leak Detection

Cpputest te permite detectar automáticamente memoria filtrada redefiniendo la familia estándar de funciones "malloc/free" para usar sus propios envoltorios en su lugar. Esto le permite detectar rápidamente las fugas y reportarlas para cada ejecución de prueba. Esto está habilitado por defecto en MakefileWorker.mk, por lo que ya está activado con los pasos descritos hasta ahora.

Para ilustrar, ¡vamos a filtrar algo de memoria en test_func() !

Volviendo a code.c, añadimos un malloc()  a la función, de la siguiente manera:

int test_func() {
    malloc(1);
    return 1;
}

Ahora, después de recompilar, se produce el siguiente error:

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

Esto muestra qué prueba causó la fuga, dónde ocurrió la fuga en el código fuente y qué había en la memoria filtrada. ¡Muy útil!

Hay un par de advertencias con esta característica:

  1. Cpputest está usando macros de preprocesador para redefinir dinámicamente todas las llamadas a las funciones estándar de gestión de memoria. Eso significa que solo funcionará para las llamadas en el código fuente bajo prueba, ya que eso es lo que se compila con las modificaciones de CppUTest. Las filtraciones en las bibliotecas vinculadas no serán detectadas.

  2. A veces, la memoria que se asigna para toda la vida del proceso no está destinada a ser liberada. Esto puede crear muchos errores molestos si estás probando un módulo con este comportamiento. Para deshabilitar la detección de fugas, puedes hacer esto:

CPPUTEST_USE_MEM_LEAK_DETECTION=N

Cpputest te permite detectar automáticamente memoria filtrada redefiniendo la familia estándar de funciones "malloc/free" para usar sus propios envoltorios en su lugar. Esto le permite detectar rápidamente las fugas y reportarlas para cada ejecución de prueba. Esto está habilitado por defecto en MakefileWorker.mk, por lo que ya está activado con los pasos descritos hasta ahora.

Para ilustrar, ¡vamos a filtrar algo de memoria en test_func() !

Volviendo a code.c, añadimos un malloc()  a la función, de la siguiente manera:

int test_func() {
    malloc(1);
    return 1;
}

Ahora, después de recompilar, se produce el siguiente error:

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

Esto muestra qué prueba causó la fuga, dónde ocurrió la fuga en el código fuente y qué había en la memoria filtrada. ¡Muy útil!

Hay un par de advertencias con esta característica:

  1. Cpputest está usando macros de preprocesador para redefinir dinámicamente todas las llamadas a las funciones estándar de gestión de memoria. Eso significa que solo funcionará para las llamadas en el código fuente bajo prueba, ya que eso es lo que se compila con las modificaciones de CppUTest. Las filtraciones en las bibliotecas vinculadas no serán detectadas.

  2. A veces, la memoria que se asigna para toda la vida del proceso no está destinada a ser liberada. Esto puede crear muchos errores molestos si estás probando un módulo con este comportamiento. Para deshabilitar la detección de fugas, puedes hacer esto:

CPPUTEST_USE_MEM_LEAK_DETECTION=N

Cpputest te permite detectar automáticamente memoria filtrada redefiniendo la familia estándar de funciones "malloc/free" para usar sus propios envoltorios en su lugar. Esto le permite detectar rápidamente las fugas y reportarlas para cada ejecución de prueba. Esto está habilitado por defecto en MakefileWorker.mk, por lo que ya está activado con los pasos descritos hasta ahora.

Para ilustrar, ¡vamos a filtrar algo de memoria en test_func() !

Volviendo a code.c, añadimos un malloc()  a la función, de la siguiente manera:

int test_func() {
    malloc(1);
    return 1;
}

Ahora, después de recompilar, se produce el siguiente error:

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

Esto muestra qué prueba causó la fuga, dónde ocurrió la fuga en el código fuente y qué había en la memoria filtrada. ¡Muy útil!

Hay un par de advertencias con esta característica:

  1. Cpputest está usando macros de preprocesador para redefinir dinámicamente todas las llamadas a las funciones estándar de gestión de memoria. Eso significa que solo funcionará para las llamadas en el código fuente bajo prueba, ya que eso es lo que se compila con las modificaciones de CppUTest. Las filtraciones en las bibliotecas vinculadas no serán detectadas.

  2. A veces, la memoria que se asigna para toda la vida del proceso no está destinada a ser liberada. Esto puede crear muchos errores molestos si estás probando un módulo con este comportamiento. Para deshabilitar la detección de fugas, puedes hacer esto:

CPPUTEST_USE_MEM_LEAK_DETECTION=N

Otras noticias

Leer más de esta categoría

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

La plataforma completa AI-native que escala con tu negocio.

© 2025 Bird

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

La plataforma completa AI-native que escala con tu negocio.

© 2025 Bird