Unidad de Pruebas C Código
unit-testing testing (30)
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.
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 forma de hacer que las pruebas unitarias en código C sean tan fáciles como las unidades que prueben códigos Java, 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.
Como novato en C, encontré que las diapositivas llamadas Desarrollo impulsado por pruebas en C son muy útiles. Básicamente, utiliza el estándar assert()
junto con &&
para entregar un mensaje, sin dependencias externas. Si alguien está acostumbrado a un marco de pruebas de pila completa, esto probablemente no funcionará :)
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
Digo casi lo mismo que ratkok, pero si tiene un giro integrado en las pruebas unitarias, entonces ...
Unity - Marco altamente recomendado para pruebas unitarias de código C
Los ejemplos en el libro que se menciona en este hilo TDD para C incrustada se escriben usando Unity (y CppUTest).
El libro de Michael Feather "Working Effectively with Legacy Code" presenta muchas técnicas específicas para pruebas de unidad 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.
En caso de que esté apuntando a plataformas Win32 o al modo de kernel NT, debería echar un vistazo a cfix .
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.
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 tiene soporte para 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.
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).
Hay una
Y Embedded Unit es un marco de prueba de unidades para Embedded C System. Su diseño fue copiado de JUnit y CUnit y más, y luego se adaptó un poco para el Sistema C Embedded. Unidad incrustada no requiere libd C estándar. Todos los objetos están asignados al área de const.
Y Tessy automatiza las pruebas unitarias de software integrado.
LibU ( http://koanlogic.com/libu ) tiene un módulo de prueba de unidad que permite dependencias de casos / casos de prueba explícitos, aislamiento de prueba, 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 ...
Me sorprende que nadie mencionó a Cutter (http://cutter.sourceforge.net/) . Puede probar C y C ++, se integra perfectamente con autotools y tiene un tutorial realmente bueno disponible.
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.
Vale la pena intentarlo y es 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 en ruby (al contrario de Cmock) y tiene muy poca dependencia en 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. Aquí también trabajo un poco más manual, 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.
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
Personalmente me gusta el framework Google Test .
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.
A esto se refiere la gente cuando habla 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 acceder 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 el código OO 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 manera 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 códigos que no son OO, que recomiendo ampliamente.
Edición : He escrito una entrada de blog sobre código de procedimiento de prueba de unidad, con fuente disponible en GitHub .
Edición : hay un nuevo libro que está saliendo de los Programadores Pragmáticos que aborda específicamente el código C de prueba de unidad, que recomiendo altamente .
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).
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.
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.
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();
}
Un marco de prueba de unidad en C es Check ; Una lista de los marcos de prueba de unidad en C se puede encontrar here y se reproduce a continuación. Dependiendo de cuántas funciones de biblioteca estándar tenga su tiempo de ejecución, es posible que no pueda 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 donde no puede incluir un solo archivo de encabezado estándar y no puede invocar una función C estándar única 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 Check, incluyendo 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 ampliamente, lo que significa que el enlace y esas opciones requieren opciones especiales, pero puede que esto no sea un gran problema para usted, especialmente si ya está usando GTK o GLib. Vea la página de inicio de GNU Autounit .
cUnidad
También usa GLib, pero no se bifurca para proteger el espacio de direcciones de las pruebas unitarias.
Nota
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, segundo, debes escribir tus pruebas en C ++, lo que significa que necesitas 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 cuán fácil es probar tu código por unidad. 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 en desarrollo temprano. Ver la página de inicio de CUnit para el Sr. Ando .
Esta lista se actualizó por última vez en marzo de 2008.
Otros:
CMocka
CMocka es un marco de prueba para C con soporte para objetos simulados. Es fácil de usar y configurar. cmocka.org oficial de cmocka.org .
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 .
Wikipedia proporciona una lista detallada de los marcos de prueba de unidad C en Lista de los marcos de prueba de unidad: C
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 debajo de su compilador cruzado, automáticamente con sus pruebas de unidad si es posible.
Utilicé RCUNIT para hacer algunas pruebas de unidad para el código incorporado en la PC antes de probar en el objetivo. Una buena abstracción de la interfaz de hardware es importante, de lo contrario, los registros de mapeo de memoria lo matarán.
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 ++.
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
cmockery en http://code.google.com/p/cmockery/
prueba lcut! - http://code.google.com/p/lcut
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 "poco profundos") para cada función en la API a través del 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 (errores), abortos, todo tipo de señales emitidas, código de retorno de programa distinto de cero y bloqueo del programa.
Ejemplos:
- Suite de prueba para fontconfig 2.8.0
- Suite de prueba para FreeType 2.4.8
CppUTest : marco altamente recomendado para pruebas unitarias de código C
Los ejemplos en el libro que se menciona en este hilo TDD para C incrustada se escriben usando CppUTest.
Minunit es un marco de prueba de unidades increíblemente simple. Lo estoy usando para probar el código del microcontrolador c para avr.
Cmockery es un proyecto recientemente lanzado que consiste en una biblioteca de C muy simple de usar para escribir pruebas unitarias.