unitarias tutorial que pruebas español unit-testing embedded arduino avr avr-gcc

unit testing - tutorial - ¿Cómo puedo probar el código de Arduino por unidad?



pruebas unitarias laravel (18)

Me gustaría poder probar mi código Arduino. Idealmente, podría ejecutar cualquier prueba sin tener que cargar el código al Arduino. ¿Qué herramientas o bibliotecas pueden ayudarme con esto?

Hay un emulador Arduino en desarrollo que podría ser útil, pero aún no parece estar listo para usar.

AVR Studio de Atmel contiene un simulador de chip que podría ser útil, pero no veo cómo lo usaría junto con el IDE de Arduino.


No ejecute pruebas unitarias en el dispositivo o emulador Arduino

El caso contra el microcontrolador Device / Emulator / Sim-based tests

El propósito de las pruebas unitarias es probar la calidad de su propio código. Las pruebas unitarias nunca deben probar la funcionalidad de factores fuera de su control.

Piénselo de esta manera: incluso si probara la funcionalidad de la biblioteca Arduino, el hardware del microcontrolador o un emulador, es absolutamente imposible que los resultados de estas pruebas le informen sobre la calidad de su propio trabajo. Por lo tanto, no hay ningún valor en escribir pruebas unitarias que se ejecutan en el dispositivo (o emulador) en absoluto.

Independientemente de si está considerando ejecutar pruebas en el dispositivo o un emulador, aún se está haciendo repetir un proceso brutalmente lento de:

  1. Ajusta tu código
  2. Compila y carga en el dispositivo Arduino
  3. Observe el comportamiento y adivine si está funcionando o no.
  4. Repetir

El paso 3 es particularmente desagradable si espera recibir mensajes de diagnóstico a través del puerto serie, pero su proyecto necesita usar el único puerto serial de hardware de Arduino. Si estaba pensando que la biblioteca de SoftwareSerial podría ser útil, debe saber que hacerlo puede interrumpir cualquier funcionalidad que requiera un tiempo preciso como generar otras señales al mismo tiempo. Este mismo problema me ha sucedido.

Nuevamente, si pusiera a prueba su boceto con un emulador y sus rutinas de tiempo crítico funcionaran perfectamente hasta que subiera al Arduino real, entonces la única lección que aprenderá es que el emulador tiene fallas, y sabiendo esto todavía ¡ no revela nada sobre la calidad de tu propio trabajo!

Si es tonto probar en el dispositivo o emulador, ¿ qué debo hacer?

Probablemente estés usando una computadora para trabajar en tu proyecto Arduino. Esa computadora es literalmente miles de veces más rápida que el microcontrolador. Escriba las pruebas para compilar y ejecutar en su computadora .

Recuerde que debe suponerse que el comportamiento de la biblioteca Arduino y del microcontrolador es correcto o al menos consistentemente incorrecto .

Cuando sus pruebas producen resultados contrarios a sus expectativas, es probable que tenga un error en su código que fue probado. Si el resultado de su prueba coincide con sus expectativas, pero el programa no se comporta correctamente cuando lo sube al Arduino, entonces sabe que sus pruebas se basaron en suposiciones incorrectas y es probable que tenga una prueba defectuosa. En cualquier caso, se le habrá dado información real sobre cuáles deberían ser sus próximos cambios de código.

Cómo construir y ejecutar pruebas en tu PC

Lo primero que debe hacer es identificar sus objetivos de prueba . Piense en qué partes de su propio código desea probar y luego asegúrese de construir su programa de tal manera que pueda aislar partes discretas para la prueba.

Si las partes que desea probar llaman cualquier función de Arduino, tendrá que proporcionar reemplazos de prueba en su programa de prueba. Esto es mucho menos trabajo de lo que parece. Sus maquetas no tienen que hacer nada más que proporcionar entradas y salidas predecibles para sus pruebas.

Cualquiera de su propio código que intente probar debe existir en archivos de origen que no sean el boceto .pde. No se preocupe, su boceto aún se compilará incluso con algún código fuente fuera del boceto. Cuando realmente se llega a eso, debe definirse poco más que el punto de entrada normal de su programa en el archivo de boceto.

¡Todo lo que queda por hacer es escribir las pruebas reales y luego compilarlas usando tu compilador C ++ favorito! Esto probablemente se ilustra mejor con un ejemplo del mundo real.

Un ejemplo real de trabajo

Uno de mis proyectos favoritos que se encuentra here tiene algunas pruebas simples que se ejecutan en la PC. Para este envío de respuestas, voy a repasar cómo me burlé de algunas de las funciones de la biblioteca Arduino y las pruebas que escribí para probar esas maquetas. Esto no es contrario a lo que dije antes sobre no probar el código de otras personas porque yo fui quien escribió las maquetas. Quería estar muy seguro de que mis maquetas eran correctas.

Fuente de mock_arduino.cpp, que contiene código que duplica alguna funcionalidad de soporte provista por la biblioteca Arduino:

#include <sys/timeb.h> #include "mock_arduino.h" timeb t_start; unsigned long millis() { timeb t_now; ftime(&t_now); return (t_now.time - t_start.time) * 1000 + (t_now.millitm - t_start.millitm); } void delay( unsigned long ms ) { unsigned long start = millis(); while(millis() - start < ms){} } void initialize_mock_arduino() { ftime(&t_start); }

Uso la siguiente maqueta para producir una salida legible cuando mi código escribe datos binarios en el dispositivo serie de hardware.

fake_serial.h

#include <iostream> class FakeSerial { public: void begin(unsigned long); void end(); size_t write(const unsigned char*, size_t); }; extern FakeSerial Serial;

fake_serial.cpp

#include <cstring> #include <iostream> #include <iomanip> #include "fake_serial.h" void FakeSerial::begin(unsigned long speed) { return; } void FakeSerial::end() { return; } size_t FakeSerial::write( const unsigned char buf[], size_t size ) { using namespace std; ios_base::fmtflags oldFlags = cout.flags(); streamsize oldPrec = cout.precision(); char oldFill = cout.fill(); cout << "Serial::write: "; cout << internal << setfill(''0''); for( unsigned int i = 0; i < size; i++ ){ cout << setw(2) << hex << (unsigned int)buf[i] << " "; } cout << endl; cout.flags(oldFlags); cout.precision(oldPrec); cout.fill(oldFill); return size; } FakeSerial Serial;

y finalmente, el programa de prueba real:

#include "mock_arduino.h" using namespace std; void millis_test() { unsigned long start = millis(); cout << "millis() test start: " << start << endl; while( millis() - start < 10000 ) { cout << millis() << endl; sleep(1); } unsigned long end = millis(); cout << "End of test - duration: " << end - start << "ms" << endl; } void delay_test() { unsigned long start = millis(); cout << "delay() test start: " << start << endl; while( millis() - start < 10000 ) { cout << millis() << endl; delay(250); } unsigned long end = millis(); cout << "End of test - duration: " << end - start << "ms" << endl; } void run_tests() { millis_test(); delay_test(); } int main(int argc, char **argv){ initialize_mock_arduino(); run_tests(); }

Esta publicación es lo suficientemente larga, así que consulte here para ver más casos de prueba en acción. Mantengo mis trabajos en progreso en otras ramas que no sean maestras, así que revisa esas ramas para ver si hay pruebas adicionales.

Elegí escribir mis propias rutinas de pruebas livianas, pero también hay disponibles marcos de prueba de unidades más robustos como CppUnit.


En ausencia de marcos de pruebas de unidades preexistentes para Arduino, he creado ArduinoUnit . Aquí hay un simple boceto de Arduino que demuestra su uso:

#include <ArduinoUnit.h> // Create test suite TestSuite suite; void setup() { Serial.begin(9600); } // Create a test called ''addition'' in the test suite test(addition) { assertEquals(3, 1 + 2); } void loop() { // Run test suite, printing results to the serial port suite.run(); }


Estamos utilizando placas Arduino para la adquisición de datos en un gran experimento científico. Posteriormente, tenemos que admitir varias placas Arduino con diferentes implementaciones. Escribí utilidades de Python para cargar dinámicamente imágenes hexagonales de Arduino durante la prueba unitaria. El código que se encuentra en el siguiente enlace es compatible con Windows y Mac OS X a través de un archivo de configuración. Para saber dónde colocan sus imágenes hexadecimales el Arduino IDE, presione la tecla Mayúsculas antes de presionar el botón de compilación (reproducir). Pulse la tecla Mayús al presionar subir para averiguar dónde se encuentra su avrdude (utilidad de carga de líneas de comando) en su sistema / versión de Arduino. Alternativamente, puede mirar los archivos de configuración incluidos y usar su ubicación de instalación (actualmente en Arduino 0020).

http://github.com/toddstavish/Python-Arduino-Unit-Testing


Este programa permite el funcionamiento automatizado de varias pruebas de unidades Arduino. El proceso de prueba se inicia en la PC, pero las pruebas se ejecutan en el hardware Arduino real. Un conjunto de pruebas unitarias generalmente se usa para probar una biblioteca Arduino. (esta

Foro Arduino: http://arduino.cc/forum/index.php?topic=140027.0

Página del proyecto GitHub: http://jeroendoggen.github.com/Arduino-TestSuite

Página en el índice de paquete Python: http://pypi.python.org/pypi/arduino_testsuite

Las pruebas unitarias se escriben con la "Biblioteca de pruebas de unidad Arduino": http://code.google.com/p/arduinounit

Los siguientes pasos se realizan para cada conjunto de pruebas unitarias:

  • Lea el archivo de configuración para descubrir qué pruebas ejecutar
  • El script compila y carga un boceto de Arduino que contiene el código de prueba de la unidad.
  • Las pruebas unitarias se ejecutan en la placa Arduino.
  • Los resultados de la prueba se imprimen sobre el puerto serie y se analizan mediante la secuencia de comandos de Python.
  • El script inicia la siguiente prueba, repitiendo los pasos anteriores para todas las pruebas que se solicitan en el archivo de configuración.
  • El script imprime un resumen que muestra una descripción general de todas las pruebas fallidas / aprobadas en el conjunto de pruebas completo.

Estoy usando Searduino al escribir el código Arduino. Searduino es un simulador de Arduino y un entorno de desarrollo (Makefiles, código C ...) que hace que sea más fácil hackear en C / C ++ usando tu editor favorito. Puede importar bocetos Arduino y ejecutarlos en el simulador.

Captura de pantalla de Searduino 0.8: http://searduino.files.wordpress.com/2014/01/jearduino-0-8.png

Se lanzará Searduino 0.9 y se grabará un video tan pronto como se realicen las últimas pruebas ... en uno o dos días.

Las pruebas en el simulador no se deben considerar como pruebas reales, pero ciertamente me han ayudado mucho a encontrar errores estúpidos / lógicos (olvidándome de pinMode(xx, OUTPUT) , etc.).

Por cierto: soy una de las personas que desarrollan Searduino.


Hay un proyecto llamado ncore , que proporciona un núcleo nativo para Arduino. Y le permite escribir pruebas para el código Arduino.

De la descripción del proyecto

El núcleo nativo le permite compilar y ejecutar bocetos Arduino en la PC, generalmente sin modificaciones. Proporciona versiones nativas de las funciones estándar de Arduino, y un interepreter de línea de comandos para dar entradas a su boceto que normalmente vendrían del propio hardware.

También en la sección "¿qué debo usar?"

Si desea construir las pruebas, necesitará cxxtest desde http://cxxtest.tigris.org . NCORE ha sido probado con cxxtest 3.10.1.



Mantenga el código específico del hardware separado o abstraído del resto para que pueda probar y depurar ese mayor "descanso" en cualquier plataforma para la que tenga buenas herramientas y con la que esté más familiarizado.

Básicamente, intente construir la mayor parte del código final de la mayor cantidad posible de bloques de creación conocidos. El trabajo específico de hardware restante será mucho más fácil y rápido. Puede terminar utilizando emuladores existentes y / o dispositivos de emulación por su cuenta. Y luego, por supuesto, tendrá que probar la realidad de alguna manera. Dependiendo de las circunstancias, eso puede o no ser muy automatizable (es decir, ¿quién o qué presionará los botones y proporcionará otras entradas? ¿Quién o qué observará e interpretará varios indicadores y salidas?).


Me complace anunciar (lo que parece ser) el primer lanzamiento estable de una gema de rubí llamada arduino_ci que construí para este propósito. Aunque está limitado a probar bibliotecas Arduino (y no bocetos independientes), permite ejecutar pruebas unitarias en Travis CI.

Suponiendo que tiene Ruby y rubygems instalados, agregar este CI a una biblioteca es sencillo. Imaginemos una biblioteca muy simple en su directorio Arduino Library, llamada DoSomething . Contiene un archivo de cabecera y esta implementación:

#include <Arduino.h> #include "do-something.h" int doSomething(void) { return 4; };

arduino_ci con arduino_ci . En primer lugar, debe agregar un Gemfile en el directorio base de su biblioteca con los siguientes contenidos:

source ''https://rubygems.org'' gem ''arduino_ci'', ''~> 0.1.7''

A continuación, ejecute la bundle install .

Luego, crea un directorio llamado test/ . (Cada archivo .cpp que coloque aquí se considerará como un conjunto de pruebas separado). Crearemos una prueba por ahora, en test/is_four.cpp :

#include <ArduinoUnitTests.h> #include "../do-something.h" unittest(library_does_something) { assertEqual(4, doSomething()); } unittest_main() // this is a macro for main(). just go with it.

Eso es todo. Si esa sintaxis assertEqual y estructura de prueba parece familiar, es porque adopté algo de la biblioteca ArduinoUnit de Matthew Murdoch a la que se refería en su respuesta .

Ahora está listo para ejecutar el bundle exec arduino_ci_remote.rb , que ejecutará esas pruebas. Podría dar salida a algo como esto:

$ bundle exec arduino_ci_remote.rb Installing library under test... ✓ Library installed at /Users/XXXXX/Documents/Arduino/libraries/DoSomething... ✓ Checking GCC version... Using built-in specs. COLLECT_GCC=g++-4.9 COLLECT_LTO_WRAPPER=/usr/local/Cellar/[email protected]/4.9.4_1/libexec/gcc/x86_64-apple-darwin16. 7.0/4.9.4/lto-wrapper Target: x86_64-apple-darwin16.7.0 Configured with: ../configure --build=x86_64-apple-darwin16.7.0 --prefix=/usr/local/Cellar/[email protected]/4.9.4_1 --libdir=/usr/local/Cellar/[email protected]/4.9.4_1/lib/gcc/4.9 --enable-languages=c,c++,objc, obj-c++,fortran --program-suffix=-4.9 --with-system-zlib --enable-libstdcxx-time=yes --enable-stage1-checking --enable-checking=release --enable-lto --enable-plugin --with-build-config=bootstrap-debug --disable-werror --with-pkgversion=''Homebrew GCC 4.9.4_1'' --with-bugurl=https://github.com/Homebrew/homebrew-core/issues MAKEINFO=missing --disable-nls --enable-multilib Thread model: posix gcc version 4.9.4 (Homebrew GCC 4.9.4_1) ...Checking GCC version ✓ Installing board package arduino:sam... ✓ Unit testing is_four.cpp... TAP version 13 1..1 # Subtest: library_does_something ok 1 - assertEqual 4 == doSomething() 1..1 ok 1 - library_does_something ...Unit testing is_four.cpp ✓ Failures: 0

Ejecutar el mismo código como parte de un trabajo de CI en Travis CI (por ejemplo, para que pueda desencadenarlo desde las solicitudes de extracción de GitHub) también es simple. Solo agregue esto a su archivo .travis.yml :

language: ruby script: - bundle install - bundle exec arduino_ci_remote.rb

Por supuesto, esta biblioteca de CI tiene mucho más poder y flexibilidad de la que tengo aquí. Aquí hay algunos otros ejemplos:


No conozco ninguna plataforma que pueda probar el código de Arduino.

Sin embargo, existe la plataforma Fritzing , que puede usar para modelar el hardware y luego exportar diagramas de PCB y esas cosas.

Vale la pena verificar.



Pruebe el simulador de circuito de Autodesk . Permite probar código y circuitos Arduino con muchos otros componentes de hardware.


Puede usar emulare : puede arrastrar y colocar un microcontrolador en un diagrama y ejecutar su código en Eclipse. La documentación en el sitio web le dice cómo configurarlo.


Puedes probar la unidad en Python con mi proyecto, PySimAVR . Arscons se usa para construir y simavr para simulación.

Ejemplo:

from pysimavr.sim import ArduinoSim def test_atmega88(): mcu = ''atmega88'' snippet = ''Serial.print("hello");'' output = ArduinoSim(snippet=snippet, mcu=mcu, timespan=0.01).get_serial() assert output == ''hello''

Prueba de inicio:

$ nosetests pysimavr/examples/test_example.py pysimavr.examples.test_example.test_atmega88 ... ok


Si desea probar el código de la unidad fuera de la MCU (en el escritorio), consulte libcheck: https://libcheck.github.io/check/

Lo usé para probar mi propio código incrustado algunas veces. Es un marco bastante robusto.


Tengo un éxito considerable probando mi código PIC al extraer el acceso al hardware y burlarlo en mis pruebas.

Por ejemplo, abstrae PORTA con

#define SetPortA(v) {PORTA = v;}

Entonces SetPortA se puede burlar fácilmente, sin agregar código de gastos generales en la versión de PIC.

Una vez que se ha probado la abstracción de hardware, pronto descubro que, en general, el código va del equipo de prueba al PIC y funciona por primera vez.

Actualizar:

Uso una #include seam para el código de la unidad, #incluyendo el código de la unidad en un archivo C ++ para la plataforma de prueba y un archivo C para el código objetivo.

Como ejemplo quiero multiplexar cuatro pantallas de 7 segmentos, un puerto manejando los segmentos y un segundo seleccionando la pantalla. El código de visualización interactúa con las pantallas a través de SetSegmentData(char) y SetDisplay(char) . Puedo simular esto en mi plataforma de prueba C ++ y verificar que obtengo los datos que espero. Para el destino utilizo #define para obtener una asignación directa sin la sobrecarga de una llamada a función

#define SetSegmentData(x) {PORTA = x;}


Utilice Proteus VSM con una biblioteca Arduino para depurar su código o para probarlo.

Es una buena práctica antes de obtener su código a bordo, pero asegúrese con los tiempos ya que la simulación no se ejecuta en tiempo real a medida que se ejecutan en el tablero.


simavr es un simulador de AVR que usa avr-gcc.

Ya es compatible con algunos microcontroladores ATTiny y ATMega, y, según el autor, es fácil agregar un poco más.

En los ejemplos se encuentra simduino, un emulador de Arduino. Es compatible con la ejecución del gestor de arranque Arduino y se puede programar con avrdude a través de Socat (un Netcat modificado).