web-dev-qa-db-fra.com

Comment puis-je tester le code Arduino?

J'aimerais pouvoir tester un peu mon code Arduino. Idéalement, je serais en mesure d'exécuter des tests sans avoir à télécharger le code sur l'Arduino. Quels outils ou bibliothèques peuvent m'aider avec cela?

Un émulateur Arduino en développement pourrait être utile, mais il ne semble pas encore prêt à être utilisé.

AVR Studio d’Atmel contient un simulateur de puce qui pourrait être utile, mais je ne vois pas comment je l’utiliserais avec l’IDE ​​Arduino.

153
Matthew Murdoch

En l'absence de framework de test unitaire préexistant pour Arduino, j'ai créé ArduinoUnit . Voici un simple croquis Arduino démontrant son utilisation:

#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();
}
60
Matthew Murdoch

Ne pas exécuter de tests unitaires sur le périphérique ou l'émulateur Arduino

Le cas contre les tests de microcontrôleur Périphérique/Émulateur/Sim

Il y a beaucoup de discussions sur ce que signifie {test unitaire} et je ne le suis pas vraiment essayer de faire un argument à ce sujet ici. Ce message est pas en vous conseillant d'éviter tous tests pratiques sur votre cible ultime Matériel. J'essaie de faire un point sur l'optimisation de votre cycle de rétroaction de développement en éliminant votre matériel cible de vos tests les plus banals et les plus fréquents. Les unités testées sont supposées être beaucoup plus petit que l'ensemble du projet.

Le but des tests unitaires est de tester la qualité de votre propre code. Les tests unitaires ne doivent généralement jamais tester la fonctionnalité de facteurs hors de votre contrôle.

Pensez-y de cette façon: même si vous deviez tester les fonctionnalités de la bibliothèque Arduino, du matériel du microcontrôleur ou d'un émulateur, il est absolument impossible que ces résultats de test vous disent tout sur la qualité de votre propre travail. Par conséquent, il est beaucoup plus utile et efficace d’écrire des tests unitaires qui ne s’exécutent pas sur le périphérique cible (ou l’émulateur).

Les tests fréquents sur votre matériel cible suivent un cycle extrêmement lent:

  1. Tweak votre code
  2. Compiler et télécharger sur un périphérique Arduino
  3. Observez le comportement et devinez si votre code correspond à vos attentes
  4. Répéter

L'étape 3 est particulièrement désagréable si vous souhaitez recevoir des messages de diagnostic via le port série, mais votre projet lui-même doit utiliser le seul port série matériel de votre Arduino. Si vous pensiez que la bibliothèque SoftwareSerial pourrait vous aider, sachez que cela risquerait de perturber toute fonctionnalité nécessitant une synchronisation précise, telle que la génération d’autres signaux en même temps. Ce problème m'est arrivé.

Encore une fois, si vous deviez tester votre croquis à l'aide d'un émulateur et que vos routines à temps critiques fonctionnaient parfaitement jusqu'à ce que vous téléchargiez l'Arduino, la seule leçon que vous allez apprendre est que l'émulateur est défectueux - et sachant que cela reste révèle rien sur la qualité du travail de le vôtre.

Si c'est idiot de tester sur le périphérique ou l'émulateur, que fais-je {devrait} _?

Vous utilisez probablement un ordinateur pour travailler sur votre projet Arduino. Cet ordinateur est beaucoup plus rapide que le microcontrôleur. Ecrivez les tests à construire et exécuté sur votre ordinateur _.

Rappelez-vous que le comportement de la bibliothèque Arduino et du microcontrôleur doit être supposé être correct ou au moins cohérent incorrect

Lorsque vos tests produisent des résultats contraires à vos attentes, vous avez probablement un défaut dans votre code qui a été testé. Si la sortie de votre test correspond à vos attentes, mais que le programme ne se comporte pas correctement lorsque vous le téléchargez sur l'Arduino, vous savez que vos tests reposent sur des hypothèses incorrectes et que votre test est probablement erroné. Dans les deux cas, vous aurez réellement compris ce que devraient être vos prochaines modifications de code. La qualité de vos commentaires est améliorée de "quelque chose est cassé" "à " ce code spécifique} est cassé ".

Comment construire et exécuter des tests sur votre PC

La première chose à faire est de identifier vos objectifs de test. Pensez aux parties de votre propre code} que vous voulez tester, puis assurez-vous de construire votre programme de manière à pouvoir isoler des parties discrètes à des fins de test.

Si les composants que vous souhaitez tester appellent des fonctions Arduino, vous devrez fournir des remplacements de maquette dans votre programme de test. C'est beaucoup moins de travail qu'il n'y parait. Vos maquettes ne doivent en réalité rien faire d'autre que fournir des entrées et des sorties prévisibles pour vos tests.

Tout code que vous souhaitez tester doit exister dans des fichiers source autres que l'esquisse .pde. Ne vous inquiétez pas, votre croquis sera toujours compilé, même avec un code source situé en dehors du croquis. En fin de compte, définissez un peu plus que le point d’entrée normal de votre programme dans le fichier d’esquisse.

Il ne reste plus qu'à écrire les tests réels, puis à les compiler à l'aide de votre compilateur C++ préféré! Ceci est probablement mieux illustré par un exemple du monde réel.

Un exemple de travail réel

Un de mes projets pour animaux de compagnie a trouvé ici a quelques tests simples exécutés sur le PC. Pour cette réponse, je vais simplement passer en revue la manière dont j'ai maquillé certaines des fonctions de la bibliothèque Arduino et les tests que j'ai écrits pour tester ces maquettes. Ce n'est pas contraire à ce que j'ai déjà dit à propos de ne pas tester le code des autres parce que c'est moi qui ai écrit les maquettes. Je voulais être très sûr que mes maquettes étaient correctes.

Source de mock_arduino.cpp, qui contient du code qui duplique certaines fonctionnalités de support fournies par la bibliothèque 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);
}

J'utilise la maquette suivante pour produire une sortie lisible lorsque mon code écrit des données binaires sur le périphérique série matériel.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;

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

#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(); }

J'ai choisi d'écrire mes propres programmes de test légers, mais des frameworks de tests unitaires plus robustes tels que CppUnit sont également disponibles.

I chose to write my own lightweight test routines, but more robust unit-test frameworks like CppUnit are also available.

108
Iron Savior

J'ai beaucoup de succès en testant mon code PIC en résumant l'accès matériel et en me moquant de mes tests.

Par exemple, je résume PORTA avec

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

Ensuite, SetPortA peut facilement être simulé, sans ajouter de code supplémentaire dans la version PIC.

Une fois que l'abstraction matérielle a été testée pendant un certain temps, je découvre rapidement que le code va généralement du banc d'essai au PIC et fonctionne pour la première fois.

Mettre à jour:

J'utilise une couture #include pour le code d'unité, #incluant le code d'unité dans un fichier C++ pour le banc d'essai, et un fichier C pour le code cible.

A titre d'exemple, je souhaite multiplexer quatre affichages à 7 segments, un port pilotant les segments et un second sélectionnant l'affichage. Le code d'affichage s'interface avec les affichages via SetSegmentData(char) et SetDisplay(char). Je peux me moquer de ceux-ci dans mon banc d'essai C++ et vérifier que je reçois les données que j'attends. Pour la cible, j'utilise #define afin d'obtenir une affectation directe sans la surcharge d'un appel de fonction

#define SetSegmentData(x) {PORTA = x;}
21
David Sykes

Il semble que emulino ferait parfaitement le travail.

Emulino est un émulateur de la plate-forme Arduino par Greg Hewgill. ( La source )

Dépôt GitHub

15
Gonzo

simavr est un simulateur AVR utilisant avr-gcc.

Il supporte déjà quelques microcontrôleurs ATTiny et ATMega et, selon l'auteur, il est facile d'en ajouter d'autres.

Dans les exemples, on trouve simduino, un émulateur Arduino. Il supporte le chargeur de démarrage Arduino et peut être programmé avec avrdude via Socat (un Netcat modifié).

11
Gonzo

Vous pouvez effectuer des tests unitaires en Python avec mon projet, PySimAVR . Arscons est utilisé pour la construction et simavr pour la simulation.

Exemple:

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'

Lancer le test:

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

Ce programme permet l'exécution automatisée de plusieurs tests unitaires Arduino. Le processus de test est démarré sur le PC, mais les tests sont exécutés sur le matériel Arduino. Un ensemble de tests unitaires est généralement utilisé pour tester une bibliothèque Arduino . 

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

Page du projet GitHub: http://jeroendoggen.github.com/Arduino-TestSuite

Page dans l'index du package Python: http://pypi.python.org/pypi/arduino_testsuite

Les tests unitaires sont écrits avec la "Bibliothèque de tests unitaires Arduino": http://code.google.com/p/arduinounit

Les étapes suivantes sont effectuées pour chaque ensemble de tests unitaires:

  • Lisez le fichier de configuration pour savoir quels tests exécuter
  • Le script compile et télécharge une esquisse Arduino contenant le code de test unitaire.
  • Les tests unitaires sont exécutés sur la carte Arduino.
  • Les résultats du test sont imprimés sur le port série et analysés par le script Python.
  • Le script démarre le test suivant, en répétant les étapes ci-dessus pour tous les tests demandés dans le fichier de configuration.
  • Le script imprime un résumé montrant une vue d'ensemble de tous les tests ayant échoué/réussi dans la suite de tests complète.
6
jeroendoggen

Je ne connais aucune plate-forme capable de tester le code Arduino.

Cependant, il existe la plate-forme Fritzing , que vous pouvez utiliser pour modéliser le matériel, puis pour exporter PCB des diagrammes et d'autres éléments.

À vérifier.

6
Yuval Adam

Nous utilisons des cartes Arduino pour l'acquisition de données dans le cadre d'une vaste expérience scientifique. Par la suite, nous devons prendre en charge plusieurs cartes Arduino avec différentes implémentations. J'ai écrit des utilitaires Python pour charger dynamiquement les images hexadécimales Arduino lors des tests unitaires. Le code figurant sur le lien ci-dessous prend en charge Windows et Mac OS X via un fichier de configuration. Pour savoir où vos images hexadécimales sont placées par l'IDE Arduino, appuyez sur la touche Maj avant de cliquer sur le bouton de création (lecture). Appuyez sur la touche Maj tout en cliquant sur Télécharger pour savoir où se trouve votre avrdude (utilitaire de téléchargement en ligne de commande) sur votre système/version d'Arduino. Vous pouvez également consulter les fichiers de configuration inclus et utiliser votre emplacement d'installation (actuellement sur Arduino 0020).

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

6
toddstavish

Conservez le code spécifique au matériel à l'écart du reste afin de pouvoir tester et déboguer ce "reste" plus important sur toute plate-forme pour laquelle vous disposez de bons outils et avec laquelle vous êtes le plus familier.

Essentiellement, essayez de construire autant de code final que possible, à partir du plus grand nombre possible de blocs de construction connus. Le travail spécifique restant lié au matériel sera alors beaucoup plus facile et plus rapide. Vous pouvez le terminer en utilisant vous-même des émulateurs et/ou des dispositifs d’émulation existants. Et puis, bien sûr, vous aurez besoin de tester la réalité. Selon les circonstances, cela peut ou peut ne pas être très facile à automatiser (par exemple, qui ou quoi appuiera sur les boutons et fournira d’autres intrants? Qui ou qui observera et interprétera divers indicateurs et résultats?).

5
Alexey Frunze

J'utilise Searduino lorsque j'écris du code Arduino. Searduino est un simulateur Arduino et un environnement de développement (Makefiles, code C, etc.) qui facilite le piratage en C/C++ à l’aide de votre éditeur favori. Vous pouvez importer des esquisses Arduino et les exécuter dans le simulateur.

Capture d'écran de Searduino 0.8: http://searduino.files.wordpress.com/2014/01/jearduino-0-8.png

Searduino 0.9 sera publié et une vidéo sera enregistrée dès que les derniers tests seront terminés… dans un jour ou deux.

Les tests sur simulateur ne doivent pas être considérés comme de véritables tests, mais ils m'ont certainement beaucoup aidé à trouver des erreurs stupides/logiques (oublier de faire pinMode(xx, OUTPUT), etc.).

BTW: Je suis l'une des personnes développant Searduino.

5
user3183814

James W. Grenning écrit d'excellents livres. Celui-ci concerne les tests unitaires du code C intégré Développement piloté par les tests pour C intégré.

4
Rafael Vega

Il existe un projet appelé ncore , qui fournit un noyau natif pour Arduino. Et vous permet d'écrire des tests pour le code Arduino.

De la description du projet

Le noyau natif vous permet de compiler et d’exécuter des esquisses Arduino sur le PC, généralement sans modification. Il fournit des versions natives de fonctions Arduino standard et un interpréteur de ligne de commande pour donner entrées dans votre esquisse qui proviendraient normalement du matériel lui-même.

Aussi sur la "qu'est-ce qu'il me faut pour l'utiliser"

Si vous voulez construire les tests, vous aurez besoin de cxxtest à partir de http://cxxtest.tigris.org . NCORE a été testé avec cxxtest 3.10.1.

3
Sudar

J'ai construit arduino_ci à cet effet. Bien qu'il soit limité au test des bibliothèques Arduino (et non à des croquis autonomes), il permet l'exécution de tests unitaires soit localement, soit sur un système de CI (comme Travis CI ou Appveyor). 

Considérez une bibliothèque très simple dans votre répertoire de bibliothèques Arduino, appelée DoSomething, avec do-something.cpp:

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

int doSomething(void) {
  return 4;
};

Vous pouvez le tester comme suit (avec un fichier de test appelé test/is_four.cpp ou quelque chose du genre):

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

C'est tout. Si la syntaxe et la structure de test assertEqual vous semblent familières, c'est parce que j'ai adopté certaines des bibliothèque ArduinoUnit de Matthew Murdoch } _ qu'il a mentionné dans sa réponse

Voir Reference.md pour plus d'informations sur le test des broches d'E/S, de l'horloge, des ports série, etc.

Ces tests unitaires sont compilés et exécutés à l'aide d'un script contenu dans une gemme Ruby. Pour des exemples de configuration, voir le README.md ou copiez simplement l'un de ces exemples:

3
Ian

Si vous souhaitez effectuer un test unitaire hors du MCU (sur le bureau), consultez libcheck: https://libcheck.github.io/check/

Je l'ai utilisé pour tester mon propre code intégré plusieurs fois. C'est un cadre assez robuste.

2
ezaquarii

Essayez Simulateur de circuit Autodesk . Il permet de tester le code Arduino et les circuits avec de nombreux autres composants matériels.

1
Sidhant Goyal

Utilisez Proteus VSM avec une bibliothèque Arduino pour déboguer votre code ou le tester.

Il est recommandé de commencer par intégrer votre code, mais assurez-vous de bien synchroniser les temps car la simulation ne s'exécute pas en temps réel, car ils s'exécutent sur le tableau.

1
sathish

Vous pouvez utiliser emulare -, faire glisser un microcontrôleur sur un diagramme et exécuter votre code dans Eclipse. La documentation sur le site Web vous explique comment le configurer.

1
Imre

En Arduino de base est écrit en C et C++, même les bibliothèques d’arduino sont écrites en C et C++. Ainsi, en termes simples, gérez simplement le code en tant que C et C++ et essayez de faire des tests unitaires. Ici, par le mot "handle", je veux dire que vous devez changer toute la syntaxe de base, telle que serial.println, à sysout, pinmode à varaibles, la boucle vide à la boucle while () qui se rompt soit au clavier, soit après quelques itérations. 

Je sais que le processus est peu long et pas si simple. D'après mon expérience personnelle, une fois que vous avez à faire avec, cela s'avère être plus fiable.

-Nandha_Frost

0
Nandha Frost