Comment puis-je tester le code Arduino?

Je voudrais pouvoir tester 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?

Il y a un émulateur Arduino en développement qui pourrait être utile, mais il ne semble pas encore être prêt à l’emploi.

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

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

Le cas contre les tests basés sur les microcontrôleurs Device / Emulator / Sim

Le but des tests unitaires est de tester la qualité de votre propre code. Les tests unitaires ne doivent jamais tester la fonctionnalité de facteurs indépendants de votre volonté.

Pensez-y de cette façon: Même si vous testiez les fonctionnalités de la bibliothèque Arduino, du matériel du microcontrôleur ou d’un émulateur, il est absolument impossible que de tels résultats de test vous renseignent sur la qualité de votre propre travail. Par conséquent, il n’y a absolument aucune valeur à écrire des tests unitaires exécutés sur le périphérique (ou l’émulateur).

Que vous envisagiez d’exécuter des tests sur l’appareil ou sur un émulateur, vous continuez à répéter un processus brutalement lent:

  1. Modifier votre code
  2. Comstackr et télécharger sur un périphérique Arduino
  3. Observez le comportement et devinez si cela fonctionne ou non.
  4. Répéter

L’étape 3 est particulièrement désagréable si vous prévoyez d’obtenir des messages de diagnostic via le port série, mais que 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 risque de perturber toute fonctionnalité nécessitant une synchronisation précise, comme la génération d’autres signaux en même temps. Ce problème même m’est arrivé.

Encore une fois, si vous deviez tester votre sketch en utilisant un émulateur et que vos routines critiques s’exécutaient parfaitement jusqu’à ce que vous les téléchargiez sur l’Arduino, la seule leçon que vous allez apprendre est que l’émulateur est défectueux et le sachant ne révèle rien sur la qualité de votre propre travail!

Si c’est idiot de tester l’appareil ou l’émulateur, que dois- je faire?

Vous utilisez probablement un ordinateur pour travailler sur votre projet Arduino. Cet ordinateur est littéralement des milliers de fois plus rapide que le microcontrôleur. Écrivez les tests à construire et à exécuter sur votre ordinateur .

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

Lorsque vos tests produisent des résultats contraires à vos attentes, vous avez probablement une faille dans votre code qui a été testée. Si votre sortie de test correspond à vos attentes, mais que le programme ne se comporte pas correctement lorsque vous le téléchargez sur Arduino, vous savez que vos tests sont basés sur des hypothèses incorrectes et que vous avez probablement un test erroné. Dans les deux cas, vous aurez une idée réelle de ce que devraient être vos prochains changements de code.

Comment créer et exécuter des tests sur votre PC

La première chose à faire est d’ identifier vos objectives de test . Pensez aux parties de votre propre code que vous souhaitez tester et assurez-vous de construire votre programme de manière à pouvoir isoler des parties discrètes pour les tester.

Si les parties 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 paraît. Vos maquettes ne doivent rien faire d’autre que de fournir des entrées et des sorties prévisibles pour vos tests.

Tout votre propre code que vous avez l’intention de tester doit exister dans des fichiers source autres que l’esquisse .pde. Ne vous inquiétez pas, votre esquisse sera toujours comstackr même avec du code source en dehors de l’esquisse. Lorsque vous vous en approchez, le fichier d’esquisse doit contenir un peu plus que le point d’entrée normal de votre programme.

Il ne vous rest plus qu’à écrire les tests réels puis à les comstackr à l’aide de votre compilateur C ++ préféré! Ceci est probablement mieux illustré avec un exemple du monde réel.

Un exemple de travail réel

Un de mes projets pour animaux de compagnie trouvé ici a quelques tests simples qui fonctionnent sur le PC. Pour cette réponse, je vais simplement vous expliquer comment j’ai intégré certaines 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 sur le fait de ne pas tester le code d’autrui car c’était moi qui écrivais les maquettes. Je voulais être très certain 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  #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 binarys sur le périphérique série matériel.

fake_serial.h

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

fake_serial.cpp

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

et enfin, le programme de test proprement dit:

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

Ce post est assez long, veuillez vous référer à mon projet sur GitHub pour voir d'autres cas de test en action. Je garde mes travaux en cours dans des twigs autres que master, vérifiez donc ces twigs pour des tests supplémentaires.

J'ai choisi d'écrire mes propres routines de test légères, mais des frameworks de test unitaires plus robustes comme CppUnit sont également disponibles.

En l’absence de toute structure de test unitaire préexistante pour Arduino, j’ai créé ArduinoUnit . Voici un simple croquis Arduino démontrant son utilisation:

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

J’ai beaucoup de succès en testant mon code PIC en extrayant l’access au matériel et en le moquant dans mes tests.

Par exemple, je résume PORTA avec

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

Ensuite, SetPortA peut facilement être moqué, sans append de code dans la version PIC.

Une fois que l’abstraction matérielle a été testée pendant un certain temps, je constate 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 un joint #include pour le code d’unité, en incluant le code d’unité dans un fichier C ++ pour le banc d’essai et un fichier C pour le code cible.

Par 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 les simuler dans mon outil de test C ++ et vérifier que j’obtiens les données attendues. Pour la cible, j’utilise #define pour obtenir une affectation directe sans la surcharge d’un appel de fonction

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

Il semble que Emulino ferait le travail parfaitement.

Emulino est un émulateur pour la plate-forme Arduino de Greg Hewgill. ( Source )

Dépôt GitHub

simavr est un simulateur AVR utilisant avr-gcc.

Il prend déjà en charge quelques microcontrôleurs ATTiny et ATMega et, selon l’auteur, il est facile d’en append.

Dans les exemples, simduino, un émulateur Arduino. Il prend en charge l’exécution du chargeur de démarrage Arduino et peut être programmé avec avrdude via Socat (un Netcat modifié).

Vous pouvez tester les unités en Python avec mon projet, PySimAVR . Arscons est utilisé pour construire 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' 

Commencer le test:

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

Je ne suis au courant d’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 et, par la suite, exporter les diagrammes de PCB et autres.

Cela vaut la peine de vérifier.

Nous utilisons des cartes Arduino pour l’acquisition de données dans une grande 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 dynamicment des images hexadécimales Arduino pendant les tests unitaires. Le code trouvé 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 shift avant d’appuyer sur le bouton de construction (lecture). Appuyez sur la touche Maj lorsque vous appuyez sur Envoyer 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

Ce programme permet l’exécution automatisée de plusieurs tests unitaires Arduino. Le processus de test est lancé 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. (ce

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 “Arduino Unit Testing Library”: 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 comstack 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 lance le test suivant, en répétant les étapes ci-dessus pour tous les tests requirejs dans le fichier de configuration.
  • Le script imprime un récapitulatif présentant une vue d’ensemble de tous les tests échoués / réussis dans la suite de tests complète.

J’utilise Searduino lors de l’écriture du code Arduino. Searduino est un simulateur Arduino et un environnement de développement (Makefiles, code C …) qui facilite le hachage en C / C ++ en utilisant votre éditeur favori. Vous pouvez importer des esquisses Arduino et les exécuter dans le simulateur.

Capture d’écran de Searduino 0.8: http://soffr.miximages.com/arduino/jearduino-0-8.png

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

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

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

Gardez le code spécifique au matériel séparé ou éloigné du rest de sorte que vous puissiez tester et déboguer ce plus grand “repos” sur toute plate-forme pour laquelle vous avez de bons outils et avec lesquels vous êtes le plus familier.

Essentiellement, essayez de créer autant de code final que possible parmi les nombreux blocs de construction connus. Le rest du travail spécifique au matériel sera alors beaucoup plus facile et rapide. Vous pouvez le terminer en utilisant vous-même des émulateurs et / ou des émulateurs existants. Et puis, bien sûr, vous devrez tester la vraie chose en quelque sorte. Selon les circonstances, cela peut ou peut ne pas être très bien automatisable (par exemple, qui ou quoi appuiera sur les boutons et fournira d’autres données? Qui ou quoi observera et interprétera divers indicateurs et résultats?).

James W. Grenning écrit d’excellents livres et celui-ci traite des tests unitaires du développement de code piloté par code C intégré pour C embarqué .

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

De la description du projet

Le kernel natif vous permet de comstackr 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 des entrées à votre esquisse qui proviendraient normalement du matériel lui-même.

Aussi sur la section “que dois-je 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.

Si vous voulez tester le code en dehors de MCU (sur le bureau), consultez libcheck: https://libcheck.github.io/check/

Je l’ai utilisé pour tester mon propre code incorporé plusieurs fois. C’est un cadre assez robuste.

Je suis heureux d’annoncer (ce qui semble être) la première version stable d’ un bijou ruby ​​appelé arduino_ci que j’ai construit à cet effet. Bien que limité aux tests des bibliothèques Arduino (et non des esquisses autonomes), il permet d’exécuter des tests unitaires sur CI CI Travis.

En supposant que Ruby et Rubygems soient installés, l’ajout de ce CI à une bibliothèque est simple. Imaginons une bibliothèque très simple dans votre répertoire de bibliothèque Arduino, appelée DoSomething . Il contient un fichier d’en-tête et cette implémentation:

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

arduino_ci avec arduino_ci . Tout d’abord, vous devez append un Gemfile dans le répertoire de base de votre bibliothèque avec le contenu suivant:

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

Ensuite, exécutez l’ bundle install .

Ensuite, créez un répertoire appelé test/ . (Chaque fichier .cpp que vous placez ici sera considéré comme une suite de tests distincte). Nous allons créer un test pour l’instant, dans test/is_four.cpp :

 #include  #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 cette syntaxe et cette structure de test assertEqual semblent familières, c’est parce que j’ai adopté une partie de la bibliothèque ArduinoUnit de Matthew Murdoch dont il a parlé dans sa réponse .

Vous êtes maintenant prêt à exécuter bundle exec arduino_ci_remote.rb , qui exécutera ces tests. Cela pourrait donner quelque chose comme ceci:

 $ 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 

Exécuter le même code dans le cadre d’un travail CI sur Travis CI (pour pouvoir le déclencher à partir de requêtes GitHub par exemple) est également simple. Ajoutez simplement ceci à votre fichier .travis.yml :

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

Bien sûr, il y a beaucoup plus de puissance et de flexibilité dans cette bibliothèque CI que dans celle-ci. Voici quelques autres exemples:

  • La bibliothèque exemple DoSomething présentée ci-dessus, utilisée pour tester arduino_ci lui-même
  • Un exemple pratique, test d’une implémentation de queue
  • Un exemple complexe, simulant une bibliothèque qui contrôle un périphérique interactif via une connexion SoftwareSerial dans le cadre de la bibliothèque Adafruit FONA

Vous pouvez utiliser emulare – vous pouvez glisser-déposer un microcontrôleur sur un diagramme et exécuter votre code dans Eclipse. La documentation sur le site Web vous indique comment la configurer.

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

C’est une bonne pratique avant de mettre votre code à bord, mais assurez-vous de respecter les délais car la simulation ne s’exécute pas en temps réel au fur et à mesure de leur exécution sur le tableau.

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