it-swarm-es.tech

Unidad de Pruebas C Código

Trabajé en un sistema integrado este verano escrito en línea recta C. Era un proyecto existente que la empresa para la que trabajo se había hecho cargo. Me he acostumbrado bastante a escribir pruebas unitarias en Java usando JUnit, pero no sabía cuál era la mejor manera de escribir pruebas unitarias para el código existente (que necesitaba refactorización), así como el nuevo código agregado al sistema.

¿Hay alguna manera de hacer que las pruebas unitarias en el código C sea tan fácil como las pruebas unitarias en el código Java con, por ejemplo, JUnit ? Cualquier información que se aplique específicamente al desarrollo integrado (compilación cruzada a la plataforma arm-linux) sería muy apreciada.

805
Paul Osborne

El marco de prueba de una unidad en C es Verificar ; se puede encontrar una lista de los marcos de prueba de unidad en C aquí y se reproduce a continuación. Dependiendo de cuántas funciones de biblioteca estándar tenga su tiempo de ejecución, puede o no poder usar una de esas.

AceUnit

AceUnit (Advanced C y Embedded Unit) se factura a sí misma como un marco de prueba cómodo de unidad de código C. Intenta imitar JUnit 4.x e incluye capacidades similares a la reflexión. AceUnit se puede usar en entornos de restricción de recursos, por ejemplo, desarrollo de software integrado y, lo que es más importante, funciona bien en entornos en los que no puede incluir un solo archivo de encabezado estándar y no puede invocar una única función C estándar desde las bibliotecas ANSI/ISO C. También tiene un puerto de Windows. No utiliza las horquillas para atrapar las señales, aunque los autores han expresado interés en agregar dicha característica. Ver la página de inicio de AceUnit .

GNU Autounit

Mucho en la misma línea que el cheque, incluyendo el forking para ejecutar pruebas unitarias en un espacio de direcciones separado (de hecho, el autor original de Check tomó prestada la idea de GNU Autounit). GNU Autounit usa GLib extensivamente, lo que significa que los enlaces y esas opciones necesitan opciones especiales, pero puede que esto no sea un gran problema para ti, especialmente si ya estás usando GTK o GLib. Vea la GNU página de inicio de sesión automática .

unidad

También usa GLib, pero no se bifurca para proteger el espacio de direcciones de las pruebas unitarias.

La noche

Estándar C, con planes para una implementación GUI de Win32. Actualmente no bifurca ni protege el espacio de direcciones de las pruebas unitarias. En el desarrollo temprano. Ver la página de inicio de CUnit .

CuTest

Un marco simple con solo un archivo .cy un archivo .h que coloque en su árbol de origen. Ver la página de inicio de CuTest .

CppUnit

El marco de pruebas de unidad principal para C++; También puedes usarlo para probar el código C. Es estable, desarrollado activamente y tiene una interfaz GUI. Las razones principales para no usar CppUnit for C son las primeras en que es bastante grande, y luego las pruebas en C++, lo que significa que necesita un compilador de C++. Si esto no suena como una preocupación, definitivamente vale la pena considerarlo, junto con otros marcos de pruebas de unidad de C++. Ver la página de inicio de CppUnit .

embUnit

embUnit (Unidad incrustada) es otro marco de prueba de unidad para sistemas embebidos. Este parece ser reemplazado por AceUnit. Página de inicio de la unidad integrada .

MinUnit

Un conjunto mínimo de macros y eso es todo! El punto es mostrar lo fácil que es realizar una prueba unitaria de su código. Ver la página de inicio de MinUnit .

Concurso para el Sr. Ando.

Una implementación de CUnit que es bastante nueva, y aparentemente aún está en desarrollo temprano. Consulte la página de inicio de Mr. Ando .

Esta lista se actualizó por última vez en marzo de 2008.

Más marcos:

CMocka

CMocka es un marco de prueba para C con soporte para objetos simulados. Es fácil de usar y configurar.

Ver la página de inicio de CMocka .

Criterio

Criterion es un marco de pruebas de unidad C multiplataforma que admite el registro automático de pruebas, pruebas parametrizadas, teorías y que puede generar múltiples formatos, incluidos TAP y JUnit XML. Cada prueba se ejecuta en su propio proceso, por lo que las señales y los fallos se pueden informar o probar si es necesario.

Vea la página de inicio de Criterion para más información.

HWUT

HWUT es una herramienta de prueba de unidad general con un gran soporte para C. Puede ayudar a crear Makefiles, generar casos de prueba masivos codificados en "tablas de iteración" mínimas, caminar a lo largo de las máquinas estatales, generar stubs C y más. El enfoque general es bastante singular: los veredictos se basan en 'stdout bueno/stdout malo'. La función de comparación, sin embargo, es flexible. Por lo tanto, cualquier tipo de script puede ser utilizado para la verificación. Puede aplicarse a cualquier idioma que pueda producir una salida estándar.

Ver la página de inicio de HWUT .

CGreen

Un moderno, portátil, prueba de unidad en varios idiomas y marco de burla para C y C++. Ofrece una notación BDD opcional, una biblioteca de simulacros, la capacidad de ejecutarlo en un solo proceso (para facilitar la depuración). Un corredor de prueba que descubre automáticamente las funciones de prueba está disponible. Pero puedes crear tu propio programáticamente.

Todas estas características (y más) se explican en el manual de CGreen .

Wikipedia proporciona una lista detallada de los marcos de prueba de unidad C en Lista de marcos de prueba de unidad: C

461
Adam Rosenfield

Personalmente me gusta el marco de prueba de Google .

La verdadera dificultad para probar el código C es romper las dependencias de los módulos externos para que pueda aislar el código en unidades. Esto puede ser especialmente problemático cuando se intentan realizar pruebas sobre códigos heredados. En este caso, a menudo me encuentro usando el enlazador para usar funciones de stubs en las pruebas.

Esto es a lo que se refiere la gente cuando hablan de " costuras ". En C, su única opción es usar el preprocesador o el enlazador para simular sus dependencias.

Un conjunto de pruebas típico en uno de mis proyectos de C podría verse así:

#include "myimplementationfile.c"
#include <gtest/gtest.h>

// Mock out external dependency on mylogger.o
void Logger_log(...){}

TEST(FactorialTest, Zero) {
    EXPECT_EQ(1, Factorial(0));
}

Tenga en cuenta que en realidad está incluyendo el archivo C y no el archivo de encabezado . Esto le da la ventaja de tener acceso a todos los miembros de datos estáticos. Aquí me burlo de mi registrador (que podría estar en logger.o y doy una implementación vacía. Esto significa que el archivo de prueba se compila y enlaza independientemente del resto del código base y se ejecuta de forma aislada.

En cuanto a la compilación cruzada del código, para que esto funcione se necesitan buenas instalaciones en el objetivo. He hecho esto con Googletest Cross compilado para Linux en una arquitectura PowerPC. Esto tiene sentido porque allí tienes un Shell completo y un sistema operativo para recopilar tus resultados. Para entornos menos ricos (que clasifico como cualquier cosa sin un sistema operativo completo), solo debe compilar y ejecutar en el Host. Debe hacer esto de todos modos para que pueda ejecutar las pruebas automáticamente como parte de la compilación.

Encuentro que probar el código C++ es generalmente mucho más fácil debido al hecho de que OO el código es en general mucho menos acoplado que el de procedimiento (por supuesto, esto depende mucho del estilo de codificación). También en C++ puede usar trucos como la inyección de dependencia y el método de anulación para obtener las costuras en el código que de otra forma se encapsula.

Michael Feathers tiene un excelente libro sobre cómo probar el código heredado . En un capítulo él cubre técnicas para tratar con el código que no es OO, que recomiendo altamente.

Editar : He escrito un blog post sobre código de procedimiento de prueba de unidad, con fuente disponible en GitHub .

Editar : hay un nuevo libro que sale de los Programadores Pragmáticos que aborda específicamente el código C de prueba de unidad que recomiendo encarecidamente .

152
mikelong

Minunit es un marco de prueba de unidades increíblemente simple. Lo estoy usando para probar el código del microcontrolador c para avr.

128
Matteo Caprari

Actualmente estoy usando el marco de prueba de unidad CuTest:

http://cutest.sourceforge.net/

Es ideal para sistemas embebidos ya que es muy ligero y simple. No tuve problemas para hacer que funcionara tanto en la plataforma de destino como en el escritorio. Además de escribir las pruebas unitarias, todo lo que se requiere es:

  • un archivo de encabezado incluido donde quiera que llame a las rutinas de CuTest
  • un solo archivo 'C' adicional para compilar/enlazar en la imagen
  • se agregó un código simple a main para configurar y llamar a las pruebas unitarias. Solo tengo esto en una función main () especial que se compila si se define UNITTEST durante la compilación.

El sistema debe admitir un montón y algunas funciones de stdio (que no todos los sistemas integrados tienen). Pero el código es lo suficientemente simple como para que puedas trabajar en alternativas a esos requisitos si tu plataforma no los tiene.

Con un uso juicioso de los bloques externos "C" {}, también admite la prueba de C++ muy bien.

40
Michael Burr

Digo casi lo mismo que ratkok, pero si tiene un giro integrado en las pruebas unitarias, entonces ...

Unidad - Marco altamente recomendado para pruebas unitarias código C.

Los ejemplos en el libro que se menciona en este hilo TDD para C incrustado se escriben usando Unity (y CppUTest).

36
Johan

También puede querer echar un vistazo a libtap , un marco de prueba de C que genera el Protocolo de prueba de todo (TAP) y, por lo tanto, se integra bien con una variedad de herramientas que surgen de esta tecnología. Se usa principalmente en el mundo del lenguaje dinámico, pero es fácil de usar y se está volviendo muy popular.

Un ejemplo:

#include <tap.h>

int main () {
    plan(5);

    ok(3 == 3);
    is("fnord", "eek", "two different strings not that way?");
    ok(3 <= 8732, "%d <= %d", 3, 8732);
    like("fnord", "f(yes|no)r*[a-f]$");
    cmp_ok(3, ">=", 10);

    done_testing();
}
32
Ovid

Existe un elegante marco de prueba de unidades para C con soporte para objetos simulados llamado cmocka . Solo requiere la biblioteca C estándar, funciona en una variedad de plataformas informáticas (incluidas las integradas) y con diferentes compiladores.

También es compatible con diferentes formatos de salida de mensajes como Subunit, Test Anything Protocol y jUnit XML.

cmocka se ha creado para trabajar también en plataformas integradas y también es compatible con Windows.

Una simple prueba se ve así:

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <cmocka.h>

/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
    (void) state; /* unused */
}

int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(null_test_success),
    };
    return cmocka_run_group_tests(tests, NULL, NULL);
}

La API está completamente documentada y varios ejemplos son parte del código fuente.

Para comenzar con cmocka, debe leer el artículo en LWN.net: Prueba de unidad con objetos simulados en C

cmocka 1.0 ha sido lanzado en febrero de 2015.

26
asn

No llegué a probar una aplicación de C heredada hasta que empecé a buscar una manera de simular funciones. Necesitaba simulacros para aislar el archivo C que quiero probar de otros. Le di una oportunidad a cmock y creo que lo adoptaré.

Cmock escanea los archivos de cabecera y genera funciones simuladas basadas en los prototipos que encuentra. Mocks le permitirá probar un archivo C en perfecto aislamiento. Todo lo que tendrá que hacer es vincular su archivo de prueba con simulacros en lugar de sus archivos de objetos reales.

Otra ventaja de cmock es que validará los parámetros pasados ​​a las funciones simuladas y le permitirá especificar qué valor de retorno deberían proporcionar las simulaciones. Esto es muy útil para probar diferentes flujos de ejecución en sus funciones.

Las pruebas consisten en las funciones típicas testA (), testB () en las que construye expectativas, llama a funciones para probar y verificar aserciones.

El último paso es generar un corredor para tus pruebas con unidad. Cmock está vinculado al marco de prueba de unidad. Unity es tan fácil de aprender como cualquier otro marco de prueba de unidad.

Bien vale la pena intentarlo y bastante fácil de entender:

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

Actualización 1

Otro marco que estoy investigando es Cmockery.

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

Es un marco puro C que soporta pruebas de unidad y burlas. No tiene dependencia de Ruby (a diferencia de Cmock) y tiene muy poca dependencia de las librerías externas.

Requiere un poco más de trabajo manual para configurar simulacros porque no genera código. Eso no representa mucho trabajo para un proyecto existente ya que los prototipos no cambiarán mucho: una vez que tenga sus mockes, no tendrá que cambiarlos por un tiempo (este es mi caso). La tipificación adicional proporciona un control completo de los simulacros. Si hay algo que no te gusta, simplemente cambias tu simulacro.

No hay necesidad de un corredor de prueba especial. Solo necesita crear una serie de pruebas y pasarla a una función run_tests. Un poco más de trabajo manual aquí también, pero definitivamente me gusta la idea de un marco autónomo autónomo.

Además contiene algunos ingeniosos trucos de C que no conocía.

En general, Cmockery necesita un poco más de comprensión de los simulacros para comenzar. Los ejemplos deberían ayudarte a superar esto. Parece que puede hacer el trabajo con mecánicos más simples.

20
Philippe A.

Como novato en C, encontré que las diapositivas llamadas Desarrollo guiado por prueba en C muy útiles. Básicamente, utiliza el assert() estándar junto con && para entregar un mensaje, sin ninguna dependencia externa. Si alguien está acostumbrado a un marco de pruebas de pila completa, esto probablemente no funcionará :)

15
chelmertz

No uso un framework, solo uso autotools "check" target support. Implementar un "principal" y utilizar asert (s).

Mi directorio de prueba Makefile.am (s) se ve como:

check_PROGRAMS = test_oe_amqp

test_oe_amqp_SOURCES = test_oe_amqp.c
test_oe_amqp_LDADD = -L$(top_builddir)/components/common -loecommon
test_oe_amqp_CFLAGS = -I$(top_srcdir)/components/common -static

TESTS = test_oe_amqp
12
navicore

Hay CUnit

Y Unidad incrustada es el marco de prueba de unidades para el sistema C incorporado. Su diseño fue copiado de JUnit y CUnit y más, y luego se adaptó un poco para el Sistema C Embedded. La unidad incorporada no requiere las libretas estándar. Todos los objetos están asignados al área de const.

Y Tessy automatiza las pruebas unitarias del software incorporado.

12
prakash

Escribimos CHEAT (alojado en GitHub ) para facilidad de uso y portabilidad.

No tiene dependencias y no requiere instalación o configuración. Solo se necesita un archivo de encabezado y un caso de prueba.

#include <cheat.h>

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

Las pruebas se compilan en un ejecutable que se encarga de ejecutar las pruebas e informar sus resultados.

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

Tiene bonitos colores también.

12
Tuplanolla

El libro de Michael Feather "Working Effectively with Legacy Code" presenta muchas técnicas específicas para la prueba de unidades durante el desarrollo de C.

Existen técnicas relacionadas con la inyección de dependencia que son específicas de C que no he visto en ningún otro lugar.

11
Frank Schwieterman

CppUTest - Marco altamente recomendado para la prueba unitaria de código C.

Los ejemplos en el libro que se mencionan en este hilo TDD para C incrustado están escritos usando CppUTest.

7
ratkok

aparte de mi obvio sesgo

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

es una forma sencilla y agradable de hacer una prueba de código C imita xUnit

6
Keith Nicholas

Utilizo CxxTest para un entorno c/c ++ incrustado (principalmente C++).

Prefiero CxxTest porque tiene un script Perl/python para construir el corredor de prueba. Después de una pequeña pendiente para configurarlo (aún más pequeño porque no tiene que escribir el corredor de prueba), es bastante fácil de usar (incluye muestras y documentación útil). La mayor parte del trabajo fue configurar el 'hardware' al que se accede el código para que pudiera realizar la prueba de la unidad/módulo de manera efectiva. Después de eso es fácil agregar nuevos casos de prueba de unidad.

Como se mencionó anteriormente, es un marco de prueba de unidad C/C++. Así que necesitarás un compilador de C++.

Guía del usuario de CxxTestWiki de CxxTest

6
Zing-

Después de leer Minunit, pensé que una mejor manera era basar la prueba en la macro afirmación, que uso mucho como una técnica de programa defensivo. Así que utilicé la misma idea de Minunit mezclado con afirmación estándar. Puedes ver mi marco (un buen nombre podría ser NoMinunit) en el blog de k0ga

Google tiene un excelente marco de prueba. https://github.com/google/googletest/blob/master/googletest/docs/primer.md

Y sí, por lo que veo, funcionará con C simple, es decir, no requiere características de C++ (puede requerir compilador de C++, no estoy seguro).

4
Paweł Hajdan
4
Landon Kuhn

Cmockery es un proyecto recientemente lanzado que consiste en una biblioteca de C muy simple de usar para escribir pruebas unitarias.

4
Alejandro Bologna

Primero, mira aquí: http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C

Mi empresa tiene una biblioteca de C que usan nuestros clientes. Usamos CxxTest (una biblioteca de pruebas unitarias de C++) para probar el código. CppUnit también funcionará. Si estás atrapado en C, recomendaría RCUNIT (pero también es bueno).

3
Kevin
2
Tony Bai

API Sanity Checker - marco de prueba para bibliotecas C/C++:

Un generador automático de pruebas de unidades básicas para una biblioteca compartida de C/C++. Puede generar datos de entrada razonables (en la mayoría, pero desafortunadamente, no todos) de los parámetros y componer casos de prueba simples (de "cordura" o de "poca profundidad") para cada función en la API mediante el análisis de declaraciones en el encabezado archivos.

La calidad de las pruebas generadas permite verificar la ausencia de errores críticos en casos de uso simples. La herramienta es capaz de generar y ejecutar pruebas generadas y detectar fallos (seguridades), abortos, todo tipo de señales emitidas, código de retorno de programa distinto de cero y bloqueo del programa.

Ejemplos:

2
linuxbuild

Utilicé RCUNIT para hacer algunas pruebas de unidad para el código incorporado en la PC antes de probar en el destino. Una buena abstracción de la interfaz de hardware es importante, de lo contrario, los registros de mapeo de memoria lo matarán.

2
Gerhard

Si estás familiarizado con JUnit, te recomiendo CppUnit. http://cppunit.sourceforge.net/cppunit-wiki

Eso es asumiendo que tienes el compilador de c ++ para hacer las pruebas unitarias. Si no, entonces estoy de acuerdo con Adam Rosenfield en que lo que quieres es verificar.

2
Kwondri

LibU ( http://koanlogic.com/libu ) tiene un módulo de prueba de unidad que permite dependencias explícitas de pruebas/casos, aislamiento de pruebas, ejecución paralela y un formateador de informes personalizable (los formatos predeterminados son XML y Txt).

La biblioteca tiene licencia BSD y contiene muchos otros módulos útiles (redes, depuración, estructuras de datos de uso común, configuración, etc.) en caso de que los necesite en sus proyectos ...

1
bongo

Me sorprende que nadie mencione Cutter (http://cutter.sourceforge.net/) Puedes probar C y C++, se integra perfectamente con autotools y tiene un tutorial realmente agradable disponible.

1
Kris

Una técnica que se debe utilizar es desarrollar el código de prueba de unidad con un marco C++ xUnit (y compilador de C++), mientras se mantiene el origen del sistema de destino como módulos C.

Asegúrese de compilar regularmente su fuente de C bajo su compilador cruzado, automáticamente con sus pruebas de unidad si es posible.

1
quamrana

Si aún está buscando los marcos de prueba, CUnitWin32 es uno para la plataforma Win32/NT.

Esto resuelve un problema fundamental que enfrenté con otros marcos de prueba. Es decir, las variables globales/estáticas están en un estado determinístico porque cada prueba se ejecuta como un proceso separado.

0
Dushara

En caso de que esté apuntando a plataformas Win32 o al modo de kernel NT, debería echar un vistazo a cfix .

0
Johannes Passing

Acabo de escribir Libcut fuera de frustración con las bibliotecas de prueba de unidades C existentes. Tiene un tipo de cadena automática de primitivas (sin necesidad de test_eq_int, test_eq_long, test_eq_short, etc ...; solo dos conjuntos diferentes para primitivas y cadenas) y consta de un archivo de encabezado. Aquí hay un breve ejemplo:

#include <libcut.h>

LIBCUT_TEST(test_abc) {
    LIBCUT_TEST_EQ(1, 1);
    LIBCUT_TEST_NE(1, 0);
    LIBCUT_TEST_STREQ("abc", "abc");
    LIBCUT_TEST_STRNE("abc", "def");
}

LIBCUT_MAIN(test_abc);

Sin embargo, solo funciona con C11.

0
kirbyfan64sos