unit-testing - test - pruebas unitarias java
Prueba de Unidad de Software Embebido (10)
¿Qué mejores prácticas ha usado en el software integrado de pruebas unitarias que son peculiares de los sistemas integrados?
Aquí hay muchas buenas respuestas, algunas cosas que no se han mencionado es tener un código de diagnóstico ejecutándose para:
- Registrar eventos HAL (interrupciones, mensajes de bus, etc.)
- Tener un código para hacer un seguimiento de tus recursos (todos los semáforos activos, actividad de subprocesos)
- Tener un mecanismo de ram de captura para copiar el contenido de la memoria y el almacenamiento persistente (disco duro o equivalente) para detectar y eliminar interbloqueos, bloqueos, pérdidas de memoria, desbordamientos de búfer, etc.
Cuando me enfrentaba a este último año, realmente quería probar en la plataforma integrada. Estaba desarrollando una biblioteca y estaba usando las llamadas RTOS y otras características de la plataforma integrada. No había nada específico disponible, así que adapté el código de UnitTest ++ para mis propósitos. Programo en la familia NetBurner y como tiene un servidor web incorporado, fue bastante sencillo escribir un corredor de prueba GUI basado en la web que ofrezca los comentarios clásicos de RED / GREEN. Resultó bastante bien , y ahora las pruebas unitarias son mucho más fáciles y me siento mucho más seguro sabiendo que el código funciona en el hardware real. Incluso uso el marco de prueba de la unidad para realizar pruebas de integración. Al principio me burlo del hardware e inyecto esa interfaz para probar. Pero eventualmente escribo algunas pruebas man-in-the-loop que ejercitan el hardware real. Resulta ser una forma mucho más simple de aprender sobre el hardware y tener una manera fácil de recuperarse de las trampas integradas. Como todas las pruebas se ejecutan desde las devoluciones de llamada AJAX hasta el servidor web, una trampa solo ocurre como resultado de invocar manualmente una prueba y el sistema siempre se reinicia limpiamente unos segundos después de la trampa.
NetBurner es lo suficientemente rápido como para que el ciclo de escritura / compilación / descarga / ejecución sea de aproximadamente 30 segundos.
Divida el código entre dispositivo dependiente e independiente del dispositivo. El código independiente se puede probar en unidades sin demasiado dolor. El código dependiente simplemente tendrá que ser probado manualmente hasta que tenga una interfaz de comunicaciones sin problemas.
Si está escribiendo la interfaz de comunicaciones, lo siento.
El software incrustado puede haber avanzado mucho en los últimos 10 años, pero generalmente hicimos lo siguiente:
- para los algoritmos que no dependían del hardware objetivo, simplemente teníamos pruebas unitarias que se construyeron y probaron en una plataforma no integrada.
- para las cosas que sí requerían el hardware, las pruebas unitarias se compilaron condicionalmente en el código para usar el hardware disponible. En nuestro caso, se trataba de un puerto serie en el objetivo que empujaba los resultados a otra máquina más capaz, donde se verificaba la corrección de las pruebas.
- Dependiendo del hardware, a veces se puede simular un dispositivo "virtual" en una plataforma no integrada. Esto usualmente consistía en tener otro hilo de ejecución (o función de señal) cambiando la memoria utilizada por el programa. Útil para E / S mapeadas en memoria pero no para IRQ y demás.
- por lo general, solo puede probar un subconjunto pequeño del código completo a la vez (debido a restricciones de memoria).
- para probar cosas sensibles al tiempo, no lo hicimos. Simple y simple. El hardware que utilizamos (8051 y 68302) no siempre funcionaba si funcionaba demasiado lento. Ese tipo de depuración tuvo que hacerse inicialmente con un CRO (osciloscopio) y (cuando teníamos algo más de dinero) un ICE (emulador en circuito).
Espero que la situación haya mejorado desde la última vez que lo hice. No desearía ese dolor en mi peor enemigo.
Es posible que desee comprobar el desarrollo impulsado por prueba para Embedded C por James W. Grenning. El libro está programado para ser publicado en agosto de 2010, pero el libro beta ya está disponible en The Pragmatic Bookshelf .
Hay muchos procesadores integrados disponibles en las tablas eval, por lo que aunque no tenga sus dispositivos de E / S reales, a menudo puede ejecutar una buena parte de sus algoritmos y lógica en uno de estos tipos de cosas, a menudo con depuración de hardware disponible vía jtag. Y las pruebas de "unidad" suelen ser más sobre tu lógica que tu i / o de todos modos. El problema es generalmente recuperar los artefactos de prueba de uno de estos entornos.
Los sistemas integrados son un tema amplio, pero en general, pensemos que es un producto de propósito específico que combina hardware y software. Mi fondo incrustado es de teléfonos móviles, que es solo un pequeño subconjunto de todos los sistemas integrados. Trataré de mantener los siguientes puntos un poco en el lado abstracto:
Resume las dependencias de hardware siempre que sea posible. De esta forma puede ejecutar las pruebas unitarias en "hardware" burlado y también probar varios casos raros / excepcionales que serían más difíciles de probar en el objetivo. Para evitar costos de abstracción, puede usar, por ejemplo, la compilación condicional.
Tener lo menos posible depende del hardware.
Las pruebas unitarias que se ejecutan en un emulador o en un entorno de compilación cruzada aún no garantizan que el código funcione en el hardware de destino. También debes probar el objetivo. Prueba en el objetivo lo antes posible.
Nos las arreglamos para obtener un poco de código dependiente del hardware probado con un simulador, utilizamos el simulador de Keil y IDE (no afiliados, solo usamos sus herramientas). Escribimos las secuencias de comandos del simulador para impulsar el ''hardware'' de una manera en que esperamos que reaccione y podemos probar de manera bastante confiable nuestro código de trabajo. Por supuesto, puede tomar algún esfuerzo modelar el hardware para algunas pruebas, pero para la mayoría de las cosas, esto funciona muy bien y nos permite hacer muchas cosas sin ningún hardware disponible. Hemos sido capaces de obtener un sistema de trabajo casi completo en el simulador antes de tener acceso al hardware y tuvimos muy pocos problemas para solucionar una vez que pusimos el código en la realidad. Esto también puede acelerar significativamente la producción de código ya que todo se puede hacer en la PC con el depurador más profundo disponible mientras se simula el chip y se intenta hacer todo en el hardware.
Han conseguido que esto funcione de manera confiable para sistemas de control complejos, interfaces de memoria, circuitos integrados de SPI personalizados e incluso una pantalla mono.
Puede haber mucho que ganar con pruebas unitarias en un entorno de PC (compilando su código con un compilador de PC C y ejecutando su código en un marco de prueba de unidad de PC), con varias condiciones:
- Esto no se aplica a la prueba de su código de bajo nivel, incluido el código de inicio, las pruebas de RAM, los controladores de hardware. Tendrás que usar pruebas unitarias más directas de esos.
- El compilador de tu sistema integrado debe ser confiable, por lo que no estás buscando los errores creados por el compilador.
- Su código tiene que ser una arquitectura en capas, con abstracción de hardware. Es posible que necesite escribir simuladores de controladores de hardware para el marco de prueba de su unidad de PC.
- Siempre debe usar los tipos
stdint.h
comouint16_t
lugar de sinunsigned int
etc.
Hemos seguido estas reglas y descubrimos que después de probar el código de capa de aplicación en un marco de prueba de unidad de PC, podemos tener una buena cantidad de confianza de que funciona bien.
Ventajas de las pruebas unitarias en la plataforma de PC:
- No se enfrenta el problema de quedarse sin espacio de ROM en su plataforma integrada debido a la adición de un marco de prueba de unidad.
- El ciclo de compilación de enlace de enlace suele ser más rápido y sencillo en la plataforma de PC (y evita el paso de "escritura / descarga" que puede durar varios minutos).
- Tiene más opciones para visualizar el progreso (algunas aplicaciones integradas tienen periféricos de E / S limitados), almacena los datos de entrada / salida para el análisis y ejecuta más pruebas que requieren mucho tiempo.
- Puede utilizar marcos de prueba de unidades basados en PC fácilmente disponibles que no estén disponibles / adecuados para una plataforma integrada.
Voz de inexperiencia aquí, pero esto es algo en lo que he estado pensando también últimamente. Me parece que el mejor enfoque sería cualquiera
A) Escriba la mayor cantidad posible de su código de aplicación independiente del hardware en un entorno de PC, antes de escribirlo en el objetivo, y escriba las pruebas de su unidad al mismo tiempo (hacerlo primero en la PC debería ayudarlo a forzarse separe las cosas independientes del hardware). De esta forma puede usar los comprobadores de unidades de su elección y luego probar las cosas dependientes del hardware a la manera antigua: con RS-232 y / o osciloscopios y pines de E / S señalizando datos dependientes del tiempo, dependiendo de qué tan rápido se tiene que ejecutar .
B) Escríbalo todo en el hardware objetivo, pero tenga un objetivo definido para compilar condicionalmente una compilación de prueba unitaria que ejecutará pruebas unitarias y generará los resultados (o datos que pueden analizarse para obtener resultados) a través de RS-232 u otros medios. Si no tienes mucha memoria, esto puede ser complicado.
Edit 7/3/2009 Simplemente tuve otro pensamiento sobre cómo probar la unidad cosas dependientes del hardware. Si sus eventos de hardware ocurren demasiado rápido para grabar con RS-232, pero no desea examinar manualmente toneladas de datos del osciloscopio para ver si sus indicadores de periferia de E / S suben y bajan como se esperaba, puede usar una PC tarjeta con DIO integrado (como la línea de tarjetas de adquisición de datos de National Instruments) para evaluar automáticamente el tiempo de esas señales. A continuación, solo tendrá que escribir el software en su PC para controlar la tarjeta de adquisición de datos para sincronizarla con la prueba de la unidad en ejecución actualmente.