Je recherche des stratégies de meilleures pratiques pour le code de test unitaire écrit pour un système embarqué. Par système embarqué, j'entends des codes tels que des pilotes de périphérique, des gestionnaires d'ISR, etc., des éléments assez proches du métal.
La plupart des tests unitaires ne sont pas possibles sans le tester sur le matériel à l'aide d'un ICE. Parfois, l'unité intégrée doit également être connectée à un autre stimulus, tel qu'un interrupteur mécanique, un moteur pas à pas et des ampoules. Cela se produit généralement de manière manuelle, l'automatisation serait géniale mais difficile et coûteuse à réaliser.
Mise à jour
Je suis tombé sur un framework de test C qui semble assez efficace pour tester des projets intégrés. Il utilise les idées de matériel moqueur. Découvrez Unity , CMock et éventuellement Ceedling .
Mise à jour 06juil2016
Entré à travers cmocka - semble être plus activement travaillé.
la source
Réponses:
Je ferais abstraction des dépendances matérielles le plus tôt possible et construirais le système sur des faisceaux de test / émulation logicielle, permettant toutes sortes de structures de test. Souvent, mon ordinateur de développement était utilisé pour tester jusqu'à 95% ou plus du système complet. Le coût de la surcharge supplémentaire (une autre couche d'abstraction) a été facilement récupéré par le code de nettoyage généré à la suite de cette abstraction.
Le test des parties véritablement baremetales d'un système embarqué est généralement une application distincte (test unitaire?) Qui enfonce le micrologiciel bien au-delà de ce que les applications peuvent même espérer atteindre. L'automatisation peut être réalisée - à un coût, mais n'est pas typique.
À moins que vous n’ayez le budget nécessaire pour construire un harnais de matériel de test unitaire, y compris ICE complet. Cela convient parfaitement, car les tests fonctionnels sont généralement petits.
la source
Un outil nécessaire pour développer est un injecteur de signal. Le système intégré disposera d’un moyen d’interfaçage avec un système hôte (généralement via un port série réservé au débogage). Utilisez cette option pour envoyer des données de test (la meilleure option est un format ASCII abrégé, de sorte qu’il soit facilement simulé par les humains).
Je suis complètement en désaccord avec cette partie de votre question: "l'automatisation serait géniale mais difficile et coûteuse à réaliser".
En utilisant TeraTerm en tant qu’injecteur de signal de port série et en écrivant des macros TeraTerm (environ 20 minutes), il existe une vaste suite de tests automatisés pouvant être exécutés sur n’importe quelle partie d’un système intégré - qu’il s’agisse de la couche de pilote, du système d’exploitation, couche 4-5, etc. TeraTerm: http://en.sourceforge.jp/projects/ttssh2/
Si le port série n'est pas disponible sur le système intégré, utilisez un outil matériel pour convertir les données du port USB / série en signaux numériques (également peu coûteux et facile à obtenir). Pendant que vous lisez ceci, j’utilise une carte à microcontrôleur à 30 $ (UBW: http://www.schmalzhaus.com/UBW32/ ) pour tester un système embarqué en vue de sa production, en injectant un stimulus via des macros TeraTerm qui est envoyé via USB / série à le microcontrôleur, qui exécute un micrologiciel modifié, qui exploite les entrées numériques et surveille les sorties numériques du système intégré cible. Parallèlement, nous avons développé un script python (utilisant pyserial et pexpect) pour automatiser l’injection et la validation des données. Rien de tout cela n'est dur et rien n'est cher. D'après mon expérience, les gestionnaires dépensent beaucoup (par exemple 30 000 dollars en équipement de test) lorsque l'équipe de test est inexpérimentée et ne peut concevoir ces solutions faciles. Malheureusement, l'équipement grand public à usage général n'inclut pas souvent les cas de test. qui attrape le pire cas / timing du système cible. La méthode peu coûteuse est donc préférable pour la couverture du test. Croyez-le ou non.
la source
C'est un problème très difficile.
En fait, j'ai conçu un harnais de tests unitaires pour un système embarqué, qui permettrait de simuler des interruptions / événements matériels et de contrôler la synchronisation de l'exécution (afin de couvrir tous les interconnexions possibles dues à la simultanéité), Les programmeurs ont plus de deux ans pour le mettre en œuvre et le mettre au travail. Ce projet est un développement exclusif, mais un projet similaire (de conception plus simple) est disponible ici .
Alors oui, l'automatisation serait géniale. Oui, c'est très difficile et coûteux à réaliser. Oui, parfois il faut faire ça. Rarement cependant, dans mon expérience dans la plupart des cas, il est plus rapide et moins coûteux d’utiliser les moteurs pas à pas et les ampoules électriques et de le faire fonctionner manuellement.
la source
Edit: ma réponse est proche de celle de mattnz, je pense ...
Je souhaite relier ce problème à d'autres, tous les tests dépendant de quelque chose d'extérieur à votre code (comme une horloge système, un système de fichiers persistant ou une base de données, contacter un service Web externe ...). Je suggère la même politique pour tous, isolez les deux niveaux en deux couches de code.
Test d'une seule opération externe
Vous voudrez peut-être tester physiquement chaque opération. Vérifiez que l'horloge système donne l'heure correcte, vérifiez qu'un fichier se souvient réellement de ce qui a été écrit, vérifiez qu'un périphérique ne reçoit qu'une seule opération ...
Ces tests:
Tester la logique (code, algorithme) qui relie les opérations externes
En disposant d'une couche de code pour effectuer les opérations externes réelles, en les cachant derrière une interface que vous pouvez facilement simuler, votre logique n'est plus dépendante des périphériques physiques réels ...
Vous pouvez simplement tester, comme tout projet classique, vous n'êtes plus dans un code difficile à tester .
la source
Les simulateurs de CPU intégrés peuvent généralement être programmés pour simuler également du matériel. Toutes les technologies de virtualisation autres que Xen le font. Mais vous devez écrire du code prétendant avoir certains registres à une adresse physique ou, sur x86, une adresse sur le bus d’E / S, puis vous devez répondre aux lectures et écritures sur ces adresses comme si votre logiciel était physique. puce dont les registres de contrôle et d'état étaient en cours d'accès.
Si vous voulez faire cela, je suggérerais de modifier QEMU. Mais ce ne serait pas facile. Ce type de tâche n’est généralement effectué que lorsque vous concevez une puce personnalisée avec un microcontrôleur et quelques autres cœurs pour vos E / S.
Le système de développement vendu par ARM Holdings répond à cela et est probablement plus facile à utiliser que le piratage informatique sur QEMU, mais il est très coûteux.
Il existe plusieurs émulateurs ARM Open Source qui exécutent une seule sous-routine, qui peut elle-même appeler d'autres sous-routines, que vous pouvez utiliser pour le débogage en optimisant les performances des sous-routines ne dépendant pas d'un accès matériel. J'ai utilisé l'un de ces logiciels avec un grand succès pour optimiser un crypteur AES pour ARM7TDMI.
Vous pouvez écrire un faisceau de test unitaire simple en C ou C ++, y associer la classe ou le sous-programme testé, puis l'exécuter dans le simulateur.
Je réfléchis à un problème similaire depuis des années: comment tester un peu le code du noyau Linux ou Mac OS X. Cela devrait être possible, mais je n'ai jamais vraiment essayé. L'une d'elles est peut-être de construire un noyau complet plutôt que de tester votre code de manière isolée, le framework de test unitaire étant directement lié à votre noyau. Vous lanceriez ensuite les tests unitaires à partir d'une sorte d'interface externe.
Peut-être serait-il plus productif d'utiliser un outil de couverture de code, puis de tester votre micrologiciel comme un package complet via son interface externe. L'outil de couverture trouverait des chemins de code qui n'avaient pas encore été testés. Vous pourrez alors ajouter des tests externes supplémentaires pour tenter d'obtenir une plus grande couverture.
la source
Comme avec le TDD non intégré, les objets fantaisie sont définitivement votre ami.
Conservez une interface propre et simple avec votre matériel sous-jacent, de sorte que tout ce qui se trouve au-dessus du niveau le plus bas puisse être simulé et que vous ayez beaucoup plus de facilité. Si vous concevez votre application intégrée avec à l'esprit la testabilité, les tests se dérouleront toujours de manière beaucoup plus fluide. .
De plus, le fait que vous ne puissiez peut-être pas tester en ligne assez tard dans le projet ne signifie pas que vous ne devriez pas non plus préparer une suite de tests en ligne.
Celles-ci ne devraient (initialement) que tester les bits qui ne pouvaient pas être testés hors ligne. Bien sûr, ce n'est pas TDD (puisque vous créez les tests à l'avance), mais votre développement TDD hors ligne devrait vous donner une bonne idée de ce à quoi votre interface matérielle doit ressembler et, par conséquent, des tests en ligne que vous devez effectuer.
En outre, si le développement en ligne coûte beaucoup plus cher que le développement hors connexion (comme c'est le cas là où je travaille), vous économiserez ainsi beaucoup de temps en ligne grâce à un ensemble de tests bien compris.
la source
Dans le développement intégré, vous effectuez souvent des analyses des limites pour vérifier le fonctionnement complet de l'application (matériel compris). Voir aussi JTAG pour le débogage du système.
Le test de routines logicielles pures sans lien avec le matériel peut être effectué à l'aide d'un framework de test d'unité C standard tel que Check . Mais méfiez-vous des limitations de mémoire (notamment stackspace, etc. sur de petits périphériques). Connaissez vos contrats! Vous pouvez également essayer d'extraire les routines logicielles du matériel pour obtenir une couverture de test plus étendue, mais cela est généralement coûteux en termes de performances sur des périphériques intégrés tels que de petits PIC ou AVR. Cependant, vous pouvez simuler des ports matériels pour obtenir une plus grande couverture (et bien sûr, vous pouvez également tester cette simulacre).
Vous pouvez également essayer d'utiliser des émulateurs pour les simluateurs de puces ou de circuits, mais ces types d'outils sont coûteux (en particulier combinés) et compliqués.
la source