las mejores prácticas cuando se realizan pruebas unitarias para el desarrollo integrado

43

Estoy buscando algunas estrategias de mejores prácticas para el código de prueba de unidad escrito para el sistema integrado. Por sistema integrado, me refiero a códigos como controladores de dispositivos, controladores ISR, etc., que están muy cerca del metal.

La mayoría de las pruebas unitarias no son posibles sin probarlas en el hardware con la ayuda de un ICE. A veces, la unidad integrada también debe conectarse a otros estímulos, como interruptores mecánicos, motores paso a paso y bombillas. Esto suele ocurrir de forma manual, la automatización sería excelente, pero difícil y costosa de lograr.

Actualizar

Encontré un marco de prueba de C que parece ser bastante exitoso en la prueba de proyectos integrados. Utiliza las ideas de burlarse del hardware. Echa un vistazo a Unity , CMock , y posiblemente Ceedling .

Actualización 06Jul2016

Encontré cmocka - parece que se está trabajando más activamente.

    
pregunta tehnyit 29.08.2011 - 11:01

7 respuestas

28

Me abstendré de las dependencias de hardware lo antes posible, y construiré el sistema con arneses de emulación / prueba de software, habilitando todo tipo de marcos de prueba. A menudo, mi PC de desarrollo se usó para probar hasta el 95% o más del sistema completo. El costo de la sobrecarga adicional (otra capa de abstracción) fue fácilmente recuperado por el código más limpio generado como resultado de esa abstracción.

La prueba de las partes verdaderamente de baremetría de un sistema integrado suele ser una aplicación separada (¿Prueba de unidad?) que hace que el firmware sea mucho más allá de lo que las aplicaciones pueden esperar lograr. La automatización se puede hacer, a un costo, pero no es típico.

A menos que, es decir, tenga el presupuesto para crear un arnés de hardware de prueba unitaria que incluya ICE completo. Esto es absolutamente bueno ya que generalmente las pruebas funcionales son pequeñas.

    
respondido por el mattnz 29.08.2011 - 11:41
15

Una herramienta necesaria para desarrollar es un inyector de señal. El sistema integrado tendrá alguna forma de interactuar con un sistema host (normalmente a través de un puerto serie reservado para la depuración). Use esto para enviar datos de prueba (la mejor opción es el formato ascii terso para que los humanos también puedan simularlo fácilmente).

Estoy totalmente en desacuerdo con esta parte de su pregunta: "la automatización sería excelente, pero difícil y costosa de lograr".

Al utilizar TeraTerm como un inyector de señal de puerto serie, y al escribir algunas macros TeraTerm (tarda unos 20 minutos), hay una gran cantidad de pruebas automatizadas que se pueden ejecutar en cualquier parte de un sistema integrado, ya sea en la capa del controlador, O / S, capa 4-5, etc. TeraTerm: enlace

Si el puerto serie no está disponible en el sistema integrado, use una herramienta de hardware para convertir los datos del puerto USB / serie en señales digitales (también de bajo costo y fácil para lograr). Mientras lees esto, estoy usando una placa de microcontrolador de $ 30 (UBW: enlace ) para probar un sistema integrado para la producción, inyectando estímulo a través de macros TeraTerm que se envía a través de USB / serie al microcontrolador, que ejecuta un firmware modificado que controla las entradas digitales y controla las salidas digitales del sistema integrado de destino. Junto con esto, desarrollamos una secuencia de comandos de python (utiliza pyserial y pexpect) para automatizar la inyección de datos y la validación de datos. Nada de esto es difícil y ninguno es caro . En mi experiencia, los gerentes gastan mucho dinero (como un equipo de prueba de $ 30,000) cuando el equipo de prueba no tiene experiencia y no puede concebir estas soluciones fáciles. Desafortunadamente, el equipo de propósito general de big-iron a menudo no incluye los casos de prueba. que captan la temporización del peor caso / etc del sistema de destino. Por lo tanto, el método económico es preferible para la cobertura de pruebas. Créalo o no.

    
respondido por el Jonathan Cline IEEE 01.09.2011 - 01:28
5

Este es un problema muy difícil.

En realidad, he diseñado un arnés de prueba de unidades para un sistema integrado, que permitiría simular eventos / interrupciones de hardware y controlar el tiempo de ejecución (para asegurarnos de que cubrimos todos los interleavings posibles debido a la concurrencia), y tomó un equipo de programadores de más de 2 años para implementarlo y ponerlo en funcionamiento. Ese proyecto es un desarrollo propio, pero un proyecto similar (más simple en diseño) está disponible aquí .

Así que sí, la automatización sería genial. Sí, es muy difícil y costoso de lograr. Sí, a veces tienes que hacer eso. Aunque rara vez, en mi experiencia en la mayoría de los casos es más rápido y económico utilizar los motores paso a paso y las bombillas y hacer que todo funcione de forma manual.

    
respondido por el littleadv 29.08.2011 - 11:12
3

Los simuladores de CPU integrados generalmente pueden programarse para simular también hardware. Todas las tecnologías de virtualización distintas de Xen hacen eso. Pero debe escribir un código que pretenda tener algunos registros en alguna dirección física o, en x86, una dirección en el bus de E / S, y luego debe responder a las lecturas y escrituras en estas direcciones como si su software fuera físico. Chip cuyos registros de control y estado se estaban accediendo.

Si desea hacer esto, sugeriría modificar QEMU. Pero no sería fácil. Este tipo de cosas generalmente solo se realiza cuando se está diseñando un chip personalizado con un microcontrolador y algunos otros núcleos para su E / S.

El sistema de desarrollo vendido por ARM Holdings proporciona esto y probablemente sea más fácil trabajar con él que piratear en QEMU, pero es muy costoso.

Hay varios emuladores ARM de código abierto que ejecutan una sola subrutina, que a su vez puede llamar a otras subrutinas, que puede usar para la depuración sintonizando el rendimiento de las subrutinas que no dependen del acceso al hardware. Utilicé uno de estos con gran éxito para optimizar un encriptador AES para ARM7TDMI.

Podría escribir un arnés de prueba unitaria simple en C o C ++, vincular la clase o subrutina que se está probando y luego ejecutarlo en el simulador.

He estado pensando en un problema similar durante años, cómo hacer una prueba unitaria del código del kernel de Linux o Mac OS X. Debería ser posible, pero en realidad nunca lo he intentado. Una posible es construir un kernel completo en lugar de probar su código de forma aislada, con el marco de prueba de la unidad vinculado directamente a su kernel. A continuación, dispararías las pruebas unitarias desde algún tipo de interfaz externa.

Tal vez sería más productivo utilizar una herramienta de cobertura de código y luego probar su firmware como un paquete completo a través de su interfaz externa. La herramienta de cobertura encontraría rutas de código que aún no se habían probado, por lo que luego podría agregar pruebas externas adicionales en un intento por obtener más cobertura.

    
respondido por el Mike Crawford 29.08.2011 - 12:13
3

Editar: mi respuesta es cercana a la de Mattnz, creo ...

Quiero relacionar este problema con otros, todas las pruebas que dependen de algo externo a su código (como el reloj del sistema, un sistema de archivos persistente o una base de datos, contactando un servicio web externo ...). Sugiero la misma política para todos ellos, aísle los dos niveles en dos capas de código.

Probando una sola operación externa

Es posible que desee probar físicamente cada operación. Verifique que el reloj del sistema dé la hora correcta, verifique que un archivo realmente recuerda lo que se ha escrito, verifique que un dispositivo reciba una sola operación ...

Estas pruebas:

  • debería ser lo más simple posible: sin algoritmo alguno, sin condición o bucle
  • puede ser dependiente del orden y dependiente de la máquina: por lo tanto, debe seguir un orden estricto y repetir en cada hardware
  • en su mayoría son estables en el transcurso de su proyecto, por lo que no necesita ejecutarlos tan a menudo
  • así que ejecutarlos manualmente es una opción; la automatización es aún mejor, si no demasiado compleja
  • Tenga en cuenta que lo que se está probando no es su código , es una herramienta que su código necesita ... Por lo tanto, probar esto podría ser opcional para usted, podría haber sido realizado por un equipo diferente. ...

Probando la lógica (código, algoritmo) que enlaza las operaciones externas

Al tener una capa de código para realizar las operaciones externas reales, ocultándolas entre una interfaz que puede simular fácilmente, su lógica ya no depende de los dispositivos físicos reales ...

Puedes probar simplemente, como cualquier proyecto regular, ya no estás en un código incrustado de difícil prueba .

    
respondido por el KLE 29.08.2011 - 19:08
3

Al igual que con TDD no incrustado, objetos simulados son definitivamente tus amigos.

Mantenga la interfaz de su hardware subyacente limpia y simple para que todo lo que esté por encima del nivel más bajo se pueda simular y le resulte mucho más fácil: si diseña su aplicación integrada teniendo en cuenta la capacidad de prueba, la prueba siempre se realizará. mucho más suavemente.

Además, el hecho de que no pueda realizar pruebas en línea hasta muy tarde en el proyecto no significa que no deba preparar un conjunto de pruebas en línea también.

Estos deberían (inicialmente) solo deberían probar los bits que no se pudieron probar fuera de línea. Claro, no es TDD (ya que está creando las pruebas por adelantado) pero su desarrollo fuera de línea de TDD debería darle una buena idea de cómo debe verse la interfaz de su hardware y, por lo tanto, qué pruebas en línea necesita realizar.

Además, si el desarrollo en línea cuesta mucho más que el desarrollo fuera de línea (como ocurre en el caso de mi trabajo), podría ahorrarle mucho tiempo en línea, teniendo un conjunto de pruebas bien comprendido para ejecutar.

    
respondido por el Mark Booth 31.08.2011 - 18:43
1

En el desarrollo integrado, a menudo se realizan análisis de límites para verificar que funcione toda la aplicación (incluido el hardware). También vea JTAG para la depuración del sistema.

Las pruebas de rutinas de software puro sin enlace al hardware pueden realizarse mediante un marco estándar de C Unit Test como Check . Pero tenga cuidado con las limitaciones de memoria (especialmente espacio de pila, etc. en dispositivos pequeños). ¡Conozca sus contratos! También puede intentar abstraer las rutinas de software del hardware para obtener una mayor cobertura de prueba, pero esto suele ser costoso en términos de rendimiento en dispositivos integrados como PIC pequeños o AVR. Sin embargo, puede simular puertos de hardware para lograr una mayor cobertura (y, por supuesto, también puede probar ese simulacro).

También puede intentar usar emuladores para los chips o simuladores de circuito, pero este tipo de herramientas son caras (especialmente en combinación) y complicadas.

    
respondido por el Falcon 29.08.2011 - 11:14

Lea otras preguntas en las etiquetas