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

La valeur de l'utilisation d'un outil de test unifié C / C ++

Portrait de Miroslaw Zielinski, directeur de la gestion des produits chez Parasoft
Le 17 avril 2023
8 min lire

L'environnement le plus efficace pour les tests de développement est celui avec une solution de test unifiée profondément intégrée à l'IDE du développeur. Par exemple, les équipes peuvent concentrer les tests sur le code le plus récemment mis à jour et à haut risque grâce à un outil centralisé comme Parasoft C/C++test.

Une solution de test unifiée avec une intégration profonde dans l'IDE du développeur fournit l'environnement le plus productif pour les tests de développement. Un outil unifié, tel que Parasoft C/C++test, permet aux équipes de concentrer leurs tests sur le code à haut risque et le plus récemment modifié.

Vérification et validation du logiciel fait partie intégrante du développement logiciel. L'effort et le budget consacrés à des projets V&V particuliers dépendent de nombreux facteurs, tels que les objectifs de sécurité fonctionnelle d'un projet, le niveau de risque commercial ou la culture qualité d'une organisation. Indépendamment de ce qui pousse une organisation à mettre en œuvre des initiatives et des processus de qualité, il faut plus que de la détermination pour produire des produits logiciels sûrs et de haute qualité.

Le choix des méthodologies de test appropriées est une tâche difficile pour de nombreuses raisons. La technologie évolue à un rythme rapide et les entreprises doivent choisir les outils de test logiciel à adopter. Dans de nombreux cas, il est également difficile de choisir entre des produits open source et commerciaux.

Cet article explique comment les techniques de test automatisées, telles que l'analyse statique avancée, la surveillance de la mémoire d'exécution, les tests unitaires automatisés et l'analyse des flux, peuvent être combinées pour améliorer les processus d'assurance qualité, et identifie les avantages de la mise en œuvre d'une solution de test unifiée. Les concepts abordés ici sont génériques et peuvent être appliqués à n'importe quel langage de programmation, mais les exemples ici ont à l'esprit les langages de programmation C et C++, créés à l'aide de Parasoft C / C ++test .

Classes de défauts et automatisation des outils

Lors de la réflexion sur d'éventuels dysfonctionnements logiciels de haut niveau, plusieurs classes d'erreurs logicielles peuvent être distinguées: les erreurs résultant d'exigences manquantes, les erreurs causées par des exigences mal spécifiées et les erreurs qui se produisent parce que les exigences ont été mal codées. Les deux premières classes de défauts logiciels entrent dans la catégorie de l'ingénierie des exigences et ne seront pas abordées ici. Je me concentre ici sur les erreurs causées par une mise en œuvre incorrecte qui comprend un large éventail de problèmes logiciels potentiels avec lesquels de nombreuses équipes sont aux prises.

Alors, qu'est-ce que cela signifie qu'une exigence a été codée de manière incorrecte ? Cela peut être beaucoup de choses. Prenons, par exemple, une exigence mal implémentée - les tests unitaires conçus pour vérifier l'échec de l'implémentation correcte et les outils d'automatisation des tests détectent et signalent le défaut. Dans un autre exemple, un outil d'analyse d'exécution peut détecter une erreur critique d'accès à la mémoire pendant un test unitaire qui est indétectable à partir des résultats du test unitaire seuls. Différents outils sont plus efficaces pour détecter certaines classes d'erreurs, comme illustré ci-dessous.

Figure 1. Défauts logiciels et paysage de stratégies de détection.

De toute évidence, tous les projets logiciels n'ont pas besoin d'utiliser toutes les technologies disponibles pour tester et améliorer la qualité des logiciels, et les organisations sont confrontées au dilemme de l'équilibre entre budget et qualité. Les projets liés à la sécurité fonctionnelle sont susceptibles de sélectionner toutes les technologies disponibles pour garantir une qualité sans compromis, ainsi que le respect des normes de sécurité des logiciels, telles que l'ISO 26262. D'autres équipes peuvent décider de ne choisir que l'analyse statique et les tests unitaires, comme ils semblent le faire. couvrent une partie importante des défauts logiciels, tandis que certaines équipes peuvent trouver un cadre de test unitaire open source suffisant.

La réticence à mettre en œuvre un large éventail de technologies de test découle souvent d'une préoccupation selon laquelle l'utilisation de plusieurs techniques impose des frais généraux importants sur le rythme du développement, sans parler du budget. C'est probablement un problème réel si les équipes décident de sélectionner des outils non intégrés. Le coût de plusieurs outils distincts, la courbe d'apprentissage et la nécessité de basculer entre différents modèles d'utilisation et interfaces peuvent être problématiques. En conséquence, les développeurs peuvent éviter d'utiliser des outils et de l'automatisation, car cela redirige leur attention de l'écriture de code vers l'utilisation des outils, ce qui diminue leur productivité.

La valeur d'une solution de test unifiée

Il est important de préciser ce que l'on attend d'une solution de test unifiée avant de discuter de sa valeur. Idéalement, une solution devrait :

  • Prise en charge de plusieurs technologies de test
  • Soyez facile à utiliser
  • Détecter les problèmes fonctionnels et les régressions
  • Assurer la traçabilité des exigences aux tests
  • Mesurer la complexité, la portabilité et la maintenabilité du code
  • Éduquez les développeurs en leur fournissant des commentaires instantanés lorsqu'ils écrivent le code
  • Fournir des informations sur la progression du développement
  • Combinez les résultats de différentes techniques pour des analyses avancées

Une solution de test unifiée et intégrée permet d'éviter un certain nombre de problèmes :

  • Plusieurs courbes d'apprentissage et problèmes d'utilisabilité liés à l'utilisation d'outils détachés avec différentes interfaces
  • Dissuader les développeurs d'écrire du code
  • Empêcher l'échange d'informations entre différents éléments d'une chaîne d'outils
Livre blanc: l'intérêt d'utiliser un outil de test unifié C / C ++

Détecter autant de défauts que possible

Les défauts logiciels appartiennent à différentes catégories, on ne peut donc pas s'attendre à ce qu'ils soient tous identifiés par une seule technique de test. Par exemple, les tests manuels au niveau du système. Pour fournir un exemple plus concret, observez l'exemple d'extrait de code suivant :

Les quelques lignes de code ci-dessus contiennent plusieurs problèmes. Plus précisément, à la ligne 16, le développeur tente d'initialiser le tampon global en utilisant la valeur d'index calculée dans le calculerIdx () fonction, mais ils ne parviennent pas à valider si elle se situe dans la plage autorisée. Même si des dizaines de sessions de tests manuels sont exécutées, elles peuvent ne pas révéler ce problème, car l'écriture d'une valeur entière dans un emplacement de mémoire aléatoire produit rarement un effet spectaculaire immédiatement.

Mais un jour, très probablement après la publication, la disposition de la mémoire peut changer et l'opération à partir de la ligne 16 plante l'application. Il est intéressant de noter que l'analyse statique peut également échouer à signaler ce problème en raison de la boucle utilisée pour calculer l'indice. Pour des raisons de performances, l'analyse des flux de données et de contrôle utilisée dans les outils d'analyse statique doit appliquer des heuristiques et des simplifications pour terminer l'analyse du code dans un délai raisonnable, et il est courant de les appliquer en boucles, ce qui signifie que certaines erreurs peuvent être manquées.

Un outil de surveillance de la mémoire, qui instrumente le code source en injectant des contrôles spéciaux et signale des opérations de mémoire incorrectes, est certain de détecter cette erreur. Les outils d'analyse d'exécution détectent les problèmes logiciels uniquement sur les chemins réellement exécutés, sans faire de suppositions - un gros avantage par rapport à l'analyse statique, car la précision des problèmes signalés est très élevée.

Dans cet exemple, la détection des erreurs de mémoire de Parasoft a facilement identifié le problème:

Une situation inverse est également possible - l'analyse statique peut détecter des problèmes que la surveillance de la mémoire d'exécution ne peut pas identifier. Par exemple, il existe la possibilité d'un déréférencement de pointeur nul à la ligne 27/28 dans l'extrait de code ci-dessous. Appelant le storePersonToFile fonction avec le personne l'argument pointeur étant nul provoque une erreur, mais cela ne se produit que si le récupérerPersonneDeBD la fonction renvoie null. Une telle condition est peu probable pendant les sessions de test du système, car la connexion à la base de données fonctionne très probablement comme prévu, de sorte que les outils de surveillance de la mémoire d'exécution restent silencieux. Cependant, l'analyse de flux dans l'outil d'analyse statique détecte facilement le pointeur nul à renvoyer à partir de cette fonction et signale un problème potentiel de déréférencement du pointeur nul.

Figure 4. Exemple de résultats d'analyse statique.

Détecter les problèmes fonctionnels et les régressions

Qu'en est-il du code qui s'exécute toujours parfaitement, mais qui ne respecte pas les exigences ? Analyse statique et dynamique ne sont pas utiles pour identifier ce genre de problèmes. La détection des écarts entre le résultat attendu et le résultat réel nécessite une comparaison des résultats de calcul avec des valeurs prédéfinies. Il existe de nombreuses façons populaires d'implémenter de telles vérifications, y compris les tests manuels au niveau du système, les tests d'intégration et les tests unitaires.

Il existe de nombreux domaines dans lesquels une solution de test unifiée peut faciliter le processus de test unitaire. La liste des avantages comprend :

  • Augmente la productivité des développeurs lors de la création de cas de test, par exemple en fournissant des assistants graphiques pour créer, modifier et configurer des cas de test.
  • S'intègre avec Tester le double frameworks, permettant des moqueries et des stubs faciles pour simuler des scénarios de test complexes, sans impliquer de grandes bases de code.
  • Met en corrélation les cas de test avec les rapports de couverture de code pour évaluer l'exhaustivité des tests.
  • Optimise les sessions de test en calculant automatiquement l'ensemble minimal de cas de test requis pour vérifier le delta de code.
  • Fusionne les rapports de couverture de code d'autres techniques de test, telles que les tests manuels/au niveau du système ou les tests d'intégration pour identifier le code non testé.
  • Trace les résultats jusqu'aux exigences pour une meilleure compréhension de l'impact des tests défaillants.

La création de tests avec des assistants graphiques ou des éditeurs peut augmenter la productivité de toute une organisation en engageant les équipes d'assurance qualité dans le processus d'écriture des tests unitaires, les faisant ainsi contribuer activement au processus de développement. Il est plus facile pour les membres de l'équipe d'assurance qualité d'utiliser des assistants graphiques que d'écrire le code de test approprié dans les éditeurs de code, car la configuration des valeurs à l'aide de formulaires de saisie (comme indiqué ci-dessous) ne nécessite pas de compétences de codage avancées et prend moins de temps, en particulier si les membres de l'équipe manquent d'expérience. . Par exemple, la capture d'écran ci-dessous montre un exemple de la capacité de test unitaire du test Parasoft C / C ++ pour C / C ++, un assistant qui aide à la création de test unitaire.

Un autre avantage de l'utilisation d'une solution de test unifiée est le retour d'information qu'elle fournit sur l'exhaustivité des tests et l'état de santé des exigences métier critiques. Des chiffres faibles dans le MC / DC Le rapport de couverture peut indiquer une couverture de succursale insuffisante, même si le rapport de couverture du relevé affiche des valeurs élevées. Ce type d'analyse nécessite une chaîne d'outils qui prend en charge plusieurs métriques de couverture, permettant aux équipes de commencer par quelque chose de simple, comme la couverture de lignes ou d'instructions, et de procéder à une couverture de code plus approfondie au fur et à mesure qu'elles progressent dans l'amélioration de leurs cas de test.

Exigences pour tester la traçabilité

Tests unitaires et les rapports de couverture des tests système sont d'excellentes sources d'informations sur le processus de test, en particulier lorsqu'ils sont combinés. Mais si les résultats des tests ne sont pas corrélés aux exigences, les équipes manquent de plusieurs informations critiques. En visionnant un rapport de traçabilité des tests aux exigences, vous pouvez déterminer rapidement l'état de la couverture des exigences. Un exemple d'un tel rapport est présenté ci-dessous :

La possibilité de corréler les exigences avec les résultats de différents types de tests est un grand avantage de l'utilisation d'une solution de test unifiée. Les tests unitaires, les tests système, les résultats des tests d'intégration, ainsi que les normes de codage et les résultats des métriques de code peuvent être corrélés pour fournir des informations sur la santé des exigences critiques et non critiques.

Combiner les résultats de différentes techniques pour des analyses avancées

Lorsque vous combinez les données des différentes techniques de test utilisées dans un projet, vous pouvez obtenir des métriques de second niveau et des analyses plus sophistiquées. L'utilisation d'une solution de test unifiée permet aux équipes d'examiner le code sous un angle complètement nouveau. Un cas de test unitaire ayant échoué peut avoir une signification différente pour un développeur, selon qu'il se produit dans un code classé à risque élevé ou faible par l'analyse des métriques de code. Si ces informations sont encore combinées avec des statistiques du contrôle de source et corrélées aux exigences, les équipes peuvent prendre de meilleures décisions sur le moment et la manière dont le code doit être corrigé.

Avec la suite d'outils Parasoft, vous pouvez tirer parti des tests basés sur les modifications pour améliorer la productivité de l'équipe. La technologie de test basée sur les modifications capture la relation entre le code source, les cas de test et les résultats de couverture de code pour calculer l'ensemble optimal de cas de test pour la vérification et la validation d'un delta de code spécifique. En effet, les équipes peuvent limiter leurs sessions de test en n'exécutant qu'un petit sous-ensemble de tests au lieu de suites de régression complètes. Cette focalisation sur le test uniquement de ce qui est absolument nécessaire se traduit par des économies importantes, en particulier pour les projets de taille moyenne ou grande.

Rassembler le tout : Parasoft C/C++test & DTP

Toutes les technologies de test décrites ci-dessus sont disponibles en Parasoft C / C ++test  et PAO Parasoft. Parasoft C/C++test est une solution de test unifiée pour les projets C et C++. C/C++test est disponible en tant que plug-in pour les IDE populaires, tels qu'Eclipse et Visual Studio. Une intégration étroite avec l'EDI évite les problèmes évoqués ci-dessus.

Les développeurs peuvent exécuter instantanément des vérifications de conformité aux normes de codage ou exécuter des tests unitaires au moment de l'écriture du code. Les membres de l'équipe QA peuvent effectuer des scénarios de test manuels pendant que l'application est surveillée pour la couverture du code et les erreurs d'exécution. Des analyses hors ligne, telles que l'analyse de flux fournie par l'analyse statique, peuvent être effectuées dans la phase d'intégration continue.

Les sessions serveur, prises en charge avec une interface de ligne de commande pratique, rapportent les résultats d'analyse à Parasoft DTP, qui agrège les informations de l'environnement de développement. Parasoft DTP offre des fonctionnalités de création de rapports étendues, notamment la possibilité d'intégrer des données provenant d'outils tiers, d'envoyer les résultats des tests aux IDE des développeurs et de calculer des analyses avancées. Les commentaires continus fournis à chaque phase du flux de travail accélèrent le développement agile et réduisent le coût de mise en conformité avec les normes de sécurité.

Il convient également de noter que l'approche des processus et de l'architecture d'assurance qualité évoquée ici ne se limite pas aux projets C / C ++. Parasoft propose des solutions similaires pour Java et C # /. NET.

Conclusion

L'amélioration de la qualité des logiciels n'est pas une entreprise homogène et nécessite différentes technologies pour éradiquer différents types de défauts logiciels. Le principal défi est de savoir comment le faire de manière efficace et efficiente en évitant de dévaster les budgets des projets et de saper le moral des développeurs.

Une solution de test unifiée avec une intégration profonde dans l'IDE du développeur fournit l'environnement le plus productif pour les tests de développement. Un outil unifié, tel que Parasoft C/C++test, avec sa capacité à unifier les métriques et les résultats de tous les aspects des tests, offre un avantage supplémentaire en permettant aux équipes de concentrer leurs tests sur le code à haut risque et le plus récemment modifié.

Essayez le test Parasoft C / C ++: une solution de test unifiée et entièrement intégrée pour le développement de logiciels C / C ++.