Webinaire en vedette : MISRA C++ 2023 : tout ce que vous devez savoir | Voir le séminaire

Pourquoi les stubs dans les tests unitaires améliorent les tests d'intégration

Portrait de Miroslaw Zielinski, directeur de la gestion des produits chez Parasoft
le 24 avril 2023
6 min lire

Si vous avez eu des difficultés à ajouter des stubs à vos tests, voici comment une option spéciale pour les stubs dans Parasoft C/C++test peut vous faciliter la génération de stubs automatiques ou utilisateur.

Un de nos clients importants et influents, travaillant sur un projet critique pour la sécurité en cours de développement selon la norme de sécurité fonctionnelle CEI 61508, nous a contactés. Ils ont demandé des conseils pour optimiser la productivité de leurs développeurs en réduisant davantage le bruit généré par les tests unitaires, c'est-à-dire le bruit produit par l'absence de stub.

Nous avons appris que la façon dont notre client effectuait ses tests unitaires était plus proche des tests d'intégration. Dans leur processus, les unités à tester n'ont pas été isolées de leurs composants dépendants (autres fichiers ou fonctions du projet), et les cas de test unitaire ont été exécutés sur la plupart des applications terminées.

Une telle approche n'est pas un test unitaire classique. Il est communément appelé test de niveau d'intégration. Les tests d'intégration sont très efficaces pour démontrer une bonne couverture de test pour les exigences fonctionnelles et non fonctionnelles. Il peut également fournir une excellente couverture de test si la couverture du code structurel est activée.

Que sont les stubs dans les tests ?

Tests unitaires consiste davantage à isoler la fonction, la méthode ou la procédure, autrement appelée unité. Cet isolement est réalisé en supprimant les dépendances et en forçant des chemins d'exécution spécifiques.

Les talons remplacent le code dans l'unité qui dépend du code à l'extérieur de l'unité. Il offre également au développeur ou au testeur la possibilité de manipuler la réponse ou le résultat du stub afin que l'unité puisse être testée de différentes manières et à diverses fins, par exemple, pour s'assurer que l'unité fonctionne de manière fiable, est sûre et, dans certains cas, est également exempt de failles de sécurité.

Pourquoi les talons sont-ils utilisés ?

La meilleure façon d'expliquer pourquoi les stubs sont utilisés et la valeur qu'ils apportent est de parcourir un cas d'utilisation. Jetez un oeil au code suivant, par exemple.

Capture d'écran du code d'un cas de test unitaire montrant une instruction "if" qui teste si le tampon pour les échantillons a été correctement alloué

Au début de la fonction, il y a une instruction if qui teste si le tampon pour les échantillons a été correctement alloué. La plupart des cas de test pour cette fonction ont été implémentés sans aucun stub, car ils se concentrent sur le flux de contrôle normal, à l'exception du cas de test, qui vérifie le comportement de la fonction lorsque l'allocation de tampon échoue. Ce cas de test nécessite un stub pour le allocateSampleBuffer fonction pour simuler la panne.

Une fois le stub ajouté, il sera appliqué de manière cohérente au code testé. Un utilisateur travaillant sur le cas de test "échec d'allocation" aura un moyen simple d'installer une fonction de rappel spéciale dans le stub, qui simulera l'effet souhaité : échec d'allocation ou ne rien faire puisque par défaut le stub renvoie un pointeur nul, qui est attendu pour le cas de test. Mais tous les autres cas de test nécessitent une attention immédiate car une configuration de stub doit être ajoutée pour eux afin d'éviter des changements indésirables dans le flux de contrôle.

Bien sûr, les développeurs peuvent revenir en arrière et reconfigurer leur cas de test pour tenir compte du stub, mais cela signifie plus de temps passé à analyser la raison de l'échec, à préparer une fonction de rappel dédiée pour le stub et à supprimer le bruit dans le processus de test, qui était principale préoccupation du client lorsqu'il nous a contactés.

Utilisation de stubs dans les tests unitaires de code C et C++

Parasoft C / C ++test facilite grandement la génération automatique de stubs ou la création manuelle de stubs. L'option est disponible à deux endroits :

Pour les stubs générés automatiquement: Configuration du test -> Exécution -> Symboles (onglet)

Capture d'écran montrant la boîte de sélection des stubs générés automatiquement dans Parasfot C/C++test avec Enable Stub Callbacks et Insert call to original function sélectionné.

Pour les stubs utilisateur et les stubs automatiques : Panneau des paramètres de stub de la vue Stubs

Capture d'écran du test Parasoft C/C++ montrant les paramètres du stub

 

 

 

 

Capture d'écran montrant l'emplacement de sortie des stubs générés automatiquement par Parasoft C/c++test

Avec l'option "Insérer l'appel à la fonction d'origine" cochée, Parasoft C / C ++test modifie la manière par défaut dont les stubs sont générés. Le changement est dans un comportement de stub lorsqu'aucun rappel n'est installé. Le stub généré avec la nouvelle option agira comme un proxy et appellera la définition de fonction d'origine à moins que l'utilisateur ne fournisse une fonction de rappel spécifique au scénario de test destinée à effectuer des activités alternatives.

Les stubs générés sans la nouvelle option, y compris les stubs hérités, n'essaieront pas d'appeler le symbole d'origine dans la situation par défaut. Si aucune fonction de rappel spécifique au cas de test n'est installée, le stub ne fera rien et renverra simplement une valeur par défaut, telle qu'un pointeur nul ou une valeur numérique nulle.

Quand utiliser les talons

Pour nous assurer que la différence est claire, comparons la situation avec l'option "Insérer l'appel à la fonction d'origine" activée et non activée pour le cas où l'utilisateur n'a pas fourni de rappel dédié.

Voici un stub généré pour goo fonction sans compromis. l'option "Insérer l'appel à la fonction d'origine". Cela fonctionne de la manière suivante :

Capture d'écran dans Parasoft C/C++test montrant un stub généré pour la fonction goo sans l'option "Insérer l'appel à la fonction d'origine".

 

 

 

 

 

Voici comment il recherche le même stub généré pour goo fonction avec l'option "Insérer l'appel à la fonction d'origine" cochée :

Capture d'écran du test Parasoft C/C++ montrant un stub généré pour la fonction goo, avec l'option "Insérer l'appel à la fonction d'origine" cochée.

Comme vous pouvez le voir, les stubs ajoutés avec la nouvelle option sont transparents pour le code testé. Ils effectuent simplement l'appel proxy à la définition d'origine, à moins que quelqu'un ne fournisse un rappel qui implémente l'action alternative souhaitée.

Différences entre les stubs, les simulacres, les espions, les pilotes et les mannequins

Il existe différents doubles de test que vous pouvez appliquer aux cas de test unitaire lors du test de logiciels. Dans les tests embarqués en temps réel du code C et C++, comme indiqué dans cet article de blog, les équipes utilisent des stubs et des mocks comme doubles mécanismes de test.

Pour tester les applications cloud et Web qui utilisent Java, C#, VB.NET ou d'autres langages, les équipes peuvent appliquer de nombreux types de doublons de test, notamment des stubs, des simulations, des espions, des mannequins et des pilotes.

  • Bouts sont de petits morceaux de code qui remplacent un autre composant pendant les tests. Le avantage d'utiliser un talon est qu'il renvoie des résultats et des réponses prédéfinis, ce qui facilite la rédaction du test. Vous pouvez exécuter vos tests même si l'autre composant ne fonctionne pas encore.
  • Se moque sont un morceau de code avec un comportement programmé qui prend la place d'un autre composant de code pendant les tests. Une simulation est un talon plus intelligent. Les simulations, d'une certaine manière, sont déterminées au moment de l'exécution puisque le code qui définit les attentes doit s'exécuter avant de faire quoi que ce soit.
  • Spies, parfois appelés simulacres partiels, enregistrent des informations en fonction de la manière dont elles ont été appelées. Par exemple, un service de messagerie qui enregistre le nombre de messages qu'il a été envoyés.
  • Nuls sont des objets passés mais jamais utilisés. Ils aident à remplir les paramètres obligatoires, comme dans un constructeur, mais n'ont aucun effet sur votre test.
  • conducteurs sont complexes à mettre en œuvre et utilisés lorsque le logiciel doit interagir avec un système externe. Ils sont le plus souvent utilisés pour les tests d'intégration.

Quelles sont les limites et les défis du stub

Dans les cas où il n'y a pas de définition originale disponible pour une fonction stub, que se passe-t-il ? Comment le stub se comporte-t-il sans un rappel qui définit le comportement alternatif ?

La beauté de C/C++test est qu'il détecte automatiquement ce genre de situation. Le stub se reconfigurera pendant le temps de construction du faisceau de test. Il n'appellera pas la définition d'origine si aucun rappel n'est installé et renverra une valeur par défaut sûre.

Stubs dans les tests d'intégration : un exemple et un résumé

Le test C/C++ réduit considérablement la quantité d'interférences entre les différents membres de l'équipe lorsqu'ils travaillent simultanément sur les cas de test dans ce type de test de semi-intégration. Un stub ajouté par le développeur A ne modifiera pas le comportement du code testé pour les cas de test ajoutés par le développeur B.

Si le développeur B décide qu'il doit configurer une action alternative pour la fonction stub pour l'un des cas de test, il peut créer une fonction de rappel spécifique au cas de test qui implémente la logique alternative souhaitée pour la fonction stub et installer ce rappel dans le stub existant en tant que partie de la configuration du scénario de test.

Découvrez comment rationaliser les tests unitaires pour les systèmes embarqués et critiques pour la sécurité.

Article connexe + ressources