Découvrez comment intégrer facilement l'analyse statique, les tests unitaires et d'autres méthodes de test de logiciels C et C++ dans votre pipeline CI/CD. Inscrivez-vous pour la démo >>

Utilisation des stubs dans les tests au niveau de l'intégration

Par Miroslaw Zielinski

3 décembre 2019

5  min lire

Il y a plusieurs mois, l'un de nos grands clients, travaillant sur un projet critique pour la sécurité en cours de développement selon la norme CEI 61508, nous a contactés pour nous demander de l'aide pour optimiser la productivité des développeurs. Le problème auquel le client était confronté était dû à la quantité de bruit dans les résultats de test générés par les développeurs travaillant simultanément sur des cas de test unitaires et configurant des stubs pour les besoins de leurs scénarios de test spécifiques.

Nous avons appris que la façon dont notre client effectuait ses tests unitaires est plus proche des tests d'intégration. Dans leur processus, les unités testées ne sont pas isolées des composants dépendants (autres fichiers du projet) et les cas de test unitaires sont exécutés sur l'application presque complète, de sorte que tous les appels entre les fonctions des projets sont câblés exactement de la même manière pendant les tests unitaires. comme dans les builds de production.

Cette approche n'est pas des tests unitaires «classiques», car elle emprunte beaucoup aux tests de niveau d'intégration. Pourtant, il est très efficace pour démontrer une bonne couverture de test pour les exigences et le code source.

Pour plus de détails sur les tests unitaires, visitez parasoft.com/solutions/unit-testing

Dans ce processus, les stubs sont ajoutés uniquement lorsqu'un scénario de test spécifique doit être simulé, généralement une injection de défaut. Prenez, par exemple, le code ci-dessous:

Au début de la fonction, il y a une instruction if qui teste si le tampon pour les échantillons a été alloué avec succès. La plupart des cas de test pour cette fonction ont été implémentés sans aucun stubs, car ils sont concentrés 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 scénario de test nécessite un stub pour que la fonction allocateSampleBuffer simule l'échec.

Une fois le stub ajouté, il sera systématiquement appliqué pour le code testé. Un utilisateur travaillant sur le cas de test «échec d'allocation» aura maintenant un moyen facile d'installer une fonction de rappel spéciale dans le stub, qui simulera l'effet souhaité (échec d'allocation, ou ne fera rien 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 scénario de test pour tenir compte du stub, mais cela signifie du temps supplémentaire 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 - ce qui était la principale préoccupation du client lorsqu'il nous a contacté.

Nous avons donc ajouté une option spéciale pour les stubs dans Parasoft C / C ++test la version 10.4.3 qui facilite beaucoup la génération de stubs automatiques ou utilisateur. La nouvelle option est disponible à deux endroits:

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

  • Pour les stubs d'utilisateur (et les stubs automatiques également): Panneau Paramètres des stubs de la vue Stubs

Avec la "Insérer un appel à la fonction d'origine" option cochée, Parasoft C / C ++test  modifie la façon dont les stubs sont générés par défaut. 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 cas de test qui est 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, et s'il n'y a pas de fonction de rappel spécifique au cas de test installée, le stub ne fera rien et renverra simplement un «défaut ”, Comme un pointeur nul ou une valeur numérique nulle.

Pour m'assurer que la différence est claire, permettez-moi de comparer rapidement la situation avec le "Insérer un appel à la fonction d'origine" option à la fois activée et sans elle, pour le cas où l'utilisateur n'a pas fourni de rappel dédié:

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

  • Voici comment il recherche le même stub généré pour goo fonction, mais cette fois en le "Insérer un appel à la fonction d'origine" option cochée:

Comme vous pouvez le voir, les stubs ajoutés avec la nouvelle option sont transparents pour le code testé et 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.

Un ingénieur expérimenté posera probablement ici une question du type «Ok, mais que se passe-t-il s'il n'y a pas de définition originale disponible pour la fonction stubbed? Comment le stub se comporte-t-il dans ce scénario lorsque je ne propose pas de rappel définissant le comportement alternatif et que je n'ai pas de définition d'origine disponible? »

Eh bien, la beauté de cette nouvelle fonctionnalité est que ce type de situation est automatiquement détecté, et le stub se reconfigurera au moment de la construction du harnais de test, de ne pas appeler la définition d'origine lorsqu'aucun rappel n'est installé, mais plutôt de renvoyer une valeur par défaut sûre. évaluer.

Cette nouvelle fonctionnalité réduit considérablement la quantité d'interférences entre les différents membres de l'équipe lors du travail simultané sur les cas de test dans ce type de test de «semi-intégration». Un stub ajouté par le développeur A ne changera 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 stubbed pour l'un des cas de test, il peut simplement créer une fonction de rappel spécifique au cas de test qui implémente la logique alternative souhaitée pour la fonction stubbed, et installe ce rappel dans le stub existant dans le cadre de la configuration du scénario de test.

Test de développement unifié pour les applications C et C ++

Par Miroslaw Zielinski

Chef de produit pour les solutions de test embarquées de Parasoft, les spécialités de Miroslaw comprennent le C / C ++, les RTOS, l'analyse de code statique, les tests unitaires, la gestion de la qualité des logiciels pour les applications critiques pour la sécurité et la conformité des logiciels aux normes de sécurité.

Recevez les dernières nouvelles et ressources sur les tests de logiciels dans votre boîte de réception.