unit-testing - serial - processing tutorial portugues




Como posso testar o código do Arduino? (13)

Não execute testes unitários no dispositivo ou no emulador do Arduino

O caso contra testes baseados em dispositivo / emulador / Sim do microcontrolador

Há muita discussão sobre o que o teste unitário significa e eu não estou realmente tentando argumentar sobre isso aqui. Este post não está dizendo para você evitar todos os testes práticos em seu hardware alvo final. Eu estou tentando fazer um ponto sobre como otimizar seu ciclo de feedback de desenvolvimento, eliminando o seu hardware de destino de seus testes mais mundanos e freqüentes. As unidades em teste são consideradas muito menores do que todo o projeto.

O objetivo do teste de unidade é testar a qualidade de seu próprio código. Os testes unitários geralmente nunca devem testar a funcionalidade de fatores fora de seu controle.

Pense desta forma: mesmo que você testasse a funcionalidade da biblioteca do Arduino, do hardware do microcontrolador ou de um emulador, é absolutamente impossível que esses resultados de testes informem sobre a qualidade do seu próprio trabalho. Portanto, é muito mais valioso e eficiente escrever testes de unidade que não são executados no dispositivo de destino (ou emulador).

Testes freqüentes no seu hardware alvo tem um ciclo dolorosamente lento:

  1. Tweak seu código
  2. Compile e carregue para o dispositivo Arduino
  3. Observe o comportamento e adivinhe se o seu código está fazendo o que você espera
  4. Repetir

O passo 3 é particularmente desagradável se você espera receber mensagens de diagnóstico via porta serial, mas o seu próprio projeto precisa usar a única porta serial de hardware do seu Arduino. Se você estava pensando que a biblioteca SoftwareSerial poderia ajudar, você deve saber que isso provavelmente interromperá qualquer funcionalidade que exija um tempo preciso, como gerar outros sinais ao mesmo tempo. Esse problema aconteceu comigo.

Novamente, se você testasse seu rascunho usando um emulador e suas rotinas de tempo crítico funcionassem perfeitamente até que você fizesse o upload para o Arduino, a única lição que você aprenderia é que o emulador é defeituoso - e saber disso ainda não revela nada sobre a qualidade do seu próprio trabalho.

Se é bobagem testar no dispositivo ou emulador, o que devo fazer?

Você provavelmente está usando um computador para trabalhar em seu projeto do Arduino. Esse computador tem ordens de magnitude mais rápidas que o microcontrolador. Escreva os testes para criar e executar no seu computador .

Lembre-se, o comportamento da biblioteca do Arduino e do microcontrolador deve ser considerado correto ou pelo menos consistentemente incorreto .

Quando seus testes geram uma saída contrária às suas expectativas, é provável que você tenha uma falha no seu código que foi testado. Se o seu resultado de teste corresponde às suas expectativas, mas o programa não se comporta corretamente quando você o carrega no Arduino, então você sabe que seus testes foram baseados em suposições incorretas e você provavelmente tem um teste falho. Em ambos os casos, você terá recebido insights reais sobre as alterações do próximo código. A qualidade do seu feedback é melhorada de " algo está quebrado" para "este código específico está quebrado" .

Como construir e executar testes no seu PC

A primeira coisa que você precisa fazer é identificar seus objetivos de teste . Pense em quais partes do seu próprio código você deseja testar e, em seguida, certifique-se de construir seu programa de forma que possa isolar partes separadas para teste.

Se as partes que você deseja testar chamarem quaisquer funções do Arduino, você precisará fornecer substituições simuladas em seu programa de teste. Isso é muito menos trabalho do que parece. Suas maquetes não precisam fazer nada além de fornecer entradas e saídas previsíveis para seus testes.

Qualquer um dos seus próprios códigos que você pretende testar precisa existir em arquivos de origem diferentes do esboço .pde. Não se preocupe, seu esboço ainda será compilado mesmo com algum código-fonte fora do esboço. Quando você realmente chegar a isso, pouco mais do que o ponto de entrada normal do seu programa deve ser definido no arquivo de esboço.

Tudo o que resta é escrever os testes reais e depois compilá-lo usando o seu compilador C ++ favorito! Isso é provavelmente melhor ilustrado com um exemplo do mundo real.

Um exemplo real de trabalho

Um dos meus projetos favoritos encontrados here tem alguns testes simples que são executados no PC. Para esta submissão de resposta, vou repassar como eu zombei de algumas das funções da biblioteca do Arduino e dos testes que escrevi para testar esses mock-ups. Isso não é contrário ao que eu disse antes sobre não testar o código de outras pessoas porque fui eu quem escreveu os mock-ups. Eu queria ter certeza de que minhas maquetas estavam corretas.

Fonte do mock_arduino.cpp, que contém código que duplica algumas funcionalidades de suporte fornecidas pela biblioteca do 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);
}

Eu uso o seguinte mock-up para produzir saída legível quando meu código grava dados binários para o dispositivo serial 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;

e finalmente, o programa de teste 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();
}

Este post é longo o suficiente, então, por favor, consulte o here para ver mais alguns casos de teste em ação. Eu mantenho meus trabalhos em andamento em outras ramificações além do mestre, portanto, verifique esses ramos também para testes extras.

Eu escolhi escrever minhas próprias rotinas de testes leves, mas estruturas de teste de unidade mais robustas como CppUnit também estão disponíveis.

Eu gostaria de poder testar meu código Arduino. Idealmente, eu seria capaz de executar qualquer teste sem ter que carregar o código para o Arduino. Quais ferramentas ou bibliotecas podem me ajudar com isso?

Existe um emulador de Arduino em desenvolvimento que pode ser útil, mas ainda não parece pronto para uso.

O AVR Studio da Atmel contém um simulador de chip que pode ser útil, mas não consigo ver como eu o utilizaria em conjunto com o Arduino IDE.


Estamos usando placas Arduino para aquisição de dados em um grande experimento científico. Posteriormente, temos que suportar várias placas Arduino com diferentes implementações. Eu escrevi utilitários Python para carregar dinamicamente as imagens hexadecimais do Arduino durante o teste de unidade. O código encontrado no link abaixo suporta Windows e Mac OS X através de um arquivo de configuração. Para descobrir onde suas imagens hexadecimais são colocadas pelo Arduino IDE, aperte a tecla Shift antes de apertar o botão de compilação (play). Aperte a tecla shift enquanto pressiona o upload para descobrir onde o seu avrdude (utilitário de upload de linha de comando) está localizado em seu sistema / versão do Arduino. Como alternativa, você pode verificar os arquivos de configuração incluídos e usar seu local de instalação (atualmente no Arduino 0020).

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


Eu construí arduino_ci para esse propósito. Embora esteja limitado a testar bibliotecas do Arduino (e não esboços autônomos), ele permite que os testes de unidade sejam executados localmente ou em um sistema de CI (como o Travis CI ou o Appveyor).

Considere uma biblioteca muito simples no diretório da biblioteca do Arduino, chamada DoSomething , com do-something.cpp :

#include <Arduino.h>
#include "do-something.h"

int doSomething(void) {
  return 4;
};

Você testaria a unidade da seguinte maneira (com um arquivo de test/is_four.cpp chamado test/is_four.cpp ou algo assim):

#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.

Isso é tudo. Se essa sintaxe assertEqual e a estrutura de teste parecem familiares, é porque eu adotei algumas das bibliotecas ArduinoUnit de Matthew Murdoch às quais ele se referiu em sua resposta .

Consulte Reference.md para obter mais informações sobre os pinos de E / S do teste de unidade, o relógio, as portas seriais, etc.

Esses testes unitários são compilados e executados usando um script contido em uma jóia rubi. Para exemplos de como configurá-lo, consulte o README.md ou apenas copie de um destes exemplos:


Eu estou usando o Searduino ao escrever o código do Arduino. O Searduino é um simulador de Arduino e um ambiente de desenvolvimento (Makefiles, código C ...) que facilita a invasão em C / C ++ usando o seu editor favorito. Você pode importar esboços do Arduino e executá-los no simulador.

Screenshot do Searduino 0.8: http://searduino.files.wordpress.com/2014/01/jearduino-0-8.png

O Searduino 0.9 será lançado e um vídeo será gravado assim que os últimos testes forem concluídos ... em um dia ou dois.

Testes no simulador não devem ser considerados como testes reais, mas certamente me ajudaram muito a encontrar erros estúpidos / lógicos (esquecer de fazer o pinMode(xx, OUTPUT) , etc.).

BTW: Eu sou uma das pessoas que desenvolvem o Searduino.


Existe um projeto chamado ncore , que fornece núcleo nativo para o Arduino. E permite que você escreva testes para o código do Arduino.

A partir da descrição do projeto

O núcleo nativo permite compilar e executar esboços do Arduino no PC, geralmente sem modificação. Ele fornece versões nativas de funções padrão do Arduino e um interepretizador de linha de comando para fornecer entradas para o seu esboço que normalmente viriam do próprio hardware.

Também na seção "o que eu preciso usar"

Se você quiser construir os testes, você precisará do cxxtest em http://cxxtest.tigris.org . NCORE foi testado com o cxxtest 3.10.1.


Experimente o simulador de circuitos da Autodesk . Ele permite testar o código e os circuitos do Arduino com muitos outros componentes de hardware.


Mantenha o código específico do hardware separado ou abstraído do resto para que você possa testar e depurar aquele "descanso" maior em qualquer plataforma para a qual você tenha boas ferramentas e com as quais você esteja mais familiarizado.

Basicamente, tente construir o máximo possível do código final de quantos blocos de construção conhecidos para o trabalho. O restante trabalho específico do hardware será então muito mais fácil e rápido. Você pode finalizá-lo usando emuladores existentes e / ou emulando dispositivos por conta própria. E então, claro, você precisará testar a coisa real de alguma forma. Dependendo das circunstâncias, isso pode ou não ser muito bem automatizável (isto é, quem ou o quê pressionará os botões e fornecerá outros insumos? Quem ou o quê irá observar e interpretar vários indicadores e saídas?).


Não tenho conhecimento de nenhuma plataforma que possa testar o código do Arduino.

No entanto, existe a plataforma Fritzing , que você pode usar para modelar o hardware e depois exportar diagramas de PCB e outras coisas.

Vale a pena verificar.


No básico, o Arduino é escrito com C e C ++, até mesmo as bibliotecas do arduino são escritas em C e C ++. Então, em termos simples, apenas manipule o código como C e C ++ e tente fazer o teste de unidade. Aqui, pela palavra "handle" quero dizer que você muda toda a sintaxe básica como serial.println para sysout, pinmode para varaibles, void loop para while () loop que quebra em keystock ou após alguma iteração.

Eu sei que este é um pequeno processo longo e não tão direto. Na minha experiência pessoal, uma vez que você tenha a ver com isso, isso se torna mais confiável.

-Nandha_Frost



Use o Proteus VSM com uma biblioteca do Arduino para depurar seu código ou testá-lo.

É uma prática recomendada antes de colocar seu código onboard, mas certifique-se de que os timings não são executados em tempo real enquanto são executados no quadro.


Você pode testar a unidade em Python com o meu projeto, PySimAVR . Arscons é usado para construção e simavr para simulação.

Exemplo:

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'

Iniciar teste:

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

simavr é um simulador AVR usando o avr-gcc.

Ele já suporta alguns microcontroladores ATTiny e ATMega, e - de acordo com o autor - é fácil adicionar mais alguns.

Nos exemplos encontra-se simduino, um emulador de Arduino. Suporta a execução do bootloader do Arduino e pode ser programado com o avrdude através do Socat (um Netcat modificado).





avr-gcc