Test de código en Arduino

Aprovechando lo que hemos creado en la entrada sobre el debug en arduino vamos a usarlo para para realizar test en el código de nuestros programas en arduino.

Al igual que el código debug, todo el código de test ha de desaparecer del código compilado cuando se quite el #define TEST. Por ejemplo en este caso cuando hacemos tests en lugar de devolver el valor de la entrada analógica fija uno por defecto, sin embargo cuando no hagamos test funcionara de forma correcta.

#ifdef TEST
  //código que se ejecutara para los test
  sensor = 128;
#else
  //Código que se ejecutara cuando no haya test
  sensor = analogRead(sensorPin);
#endif

También necesitamos una función que nos envíe por el puerto en serie si un test ha sido correcto o incorrecto. Como verificar le null a veces tiene su complejidad se ha creado otra función propia para ello.

void test(bool t){
  if(!t){
    Serial.println("False");
  } else {
    Serial.println("True");
  }
}

void testNull(void* o){
  if(o == ((void *)0)){
    Serial.println("is null");
   } else {
    Serial.println("is no null");
  }
}

En lugar de llamarlas directamente se hace usando las macros TEST(X) y TESTNULL(X). Para que desaparezcan cuando se desactiven los test.

¿Pero que pasa si cuando un test falla queremos para la ejecución? Por ejemplo porque puede ser peligroso para el circuito o porque algún elemento no se ha inicializado correctamente. Para eso se han definido dos funciones idénticas pero dentro de la etiqueta ERROR ya que pueden ser utiles en la ejecución habitual del programa cuando ya no se hacen test. ASSERT(X) y ASSERTNONULL(X)*. La diferencia con TEST es que si son ciertas paran la ejecución del programa llamando a la función stop() definida en la librería.

void stop(){
  Serial.print("STOP!!!");
  Serial.flush();
  noInterrupts();
  while(1){
    delay(1000);
  };
}

Esta función bloquea la ejecución del código creando un bucle infinito y bloqueando las interrupciones. Es una salida segura cuando no sabes como continuar y hacerlo podría dañar algo. También se le puede llamar directamente usando la macro STOP

Un ejemplo de uso:

#define DEBUG
#define TRACE
#define INFO
#define ERROR
#define TEST

#include <Debug.h>

int c = 0;

void(* reset) (void) = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  TRACEMSG("Start loop");
  inc();
  TEST(c 40)
      STOP
  #endif

  delay(500);
}

void inc(){
  ENTER
    c++;
  EXIT
}

La librería puede encontrarse en mi github

Este texto mejorado y ampliado forma parte de mi libro sobre como mejorar tus programas en Arduino. Puedes echarle un vistazo aquí.