Par Olenka Van Schendel | 19 mai 2020

Sur les systèmes modernes et distribués, les tests unitaires sont sans doute l’élément le plus efficace de votre stratégie de test. Une batterie de tests unitaires bien conçus « impose » la qualité de votre application au fur et à mesure de son développement – et idéalement même avant.  Les éléments des tests unitaires sont ensuite réutilisés en continu pendant toute la durée de vie de l’application afin de détecter toute régression dans le système.

Mais comment les tests unitaires peuvent-ils profiter aux applications existantes sur IBM i – et en particulier à celles qui n’ont pas été conçues dans une optique « unitaire », et où le code monolithique a toujours été la norme ?

Dans cet article, nous examinerons l’importance des tests unitaires en général et évaluerons la pertinence de cette technique sur IBM i.

1. La qualité à partir de la quantité

Les tests unitaires sont souvent négligés au profit de techniques plus orientées « business » comme les tests fonctionnels ou de bout en bout.  Les tests unitaires prennent un temps précieux aux développeurs, surtout sur une base de code ancien comme IBM i qui n’est pas particulièrement structuré en « unités ».  Alors comment un test unitaire par « boîte blanche », sans connaissance des fonctionnalités réelles de l’application, peut-il sauvegarder la qualité et la précision de votre système, sans parler de la réduction de vos coûts de développement ?

La solution réside dans la quantité et la couverture des tests.

Les tests unitaires impliquent la création d’une multitude de petits cas de tests très simples.  Chaque test isole une section particulière du code (comme une procédure, un sous-programme, un bloc conditionnel), définissant le succès ou l’échec en termes de valeurs attendues des paramètres de sortie pour une entrée donnée.  L’exécution du test est ensuite stockée comme « ligne de base », et les tests ultérieurs sont évalués par rapport à ce résultat.  Cela rend les tests unitaires très efficaces pour détecter les régressions dans le système.  Ils peuvent être réutilisés, regroupés et exécutés dans le cadre d’une suite à tout moment, par exemple après chaque build du système, après un changement d’environnement, ou avant qu’un composant particulier ne soit transféré aux testeurs QA.  Les tests unitaires créés au début de la phase de développement peuvent être utilisés plus tard comme « smoke test » d’une application, afin de détecter les erreurs basiques et éviter de perdre du temps avec des tests plus sophistiqués.

2. Classification des défauts

En effet, les classifications de défauts typiques révèlent que les défauts des logiciels peuvent être attribués à une grande variété de causes, notamment :

  • Erreurs dans la spécification, la conception et la mise en œuvre du logiciel et du système
  • Erreurs dans l’utilisation du système
  • Conditions environnementales
  • Dommages intentionnels
  • Conséquences potentielles des erreurs antérieures

Des enquêtes récentes ont montré que jusqu’à 55 % de tous les défauts sont dus à des erreurs présentes dans le cahier des charges.

Il a également été observé qu’environ 40 % du temps d’un testeur est consacré à des questions environnementales, ce qui a un impact important sur la qualité et la productivité.

Les nombreuses causes « périphériques » des défauts signifient que les coûts globaux des tests peuvent être considérablement réduits en réutilisant les cas de tests unitaires dans les « smoke tests », avant d’entreprendre des tests de systèmes coûteux à grande échelle.

ARCAD for Enterprise DevOps Datasheet

ARCAD for Enterprise DevOps

Datasheet

Découvrez comment ARCAD for DevOps permet de contrôler les coûts et d’accélérer les déploiements d’applications dans des environnements technologiques hétérogènes.

3. « Shift Left » – détecter les erreurs le plus tôt possible

Les tests unitaires ne sont qu’une des nombreuses techniques des développeurs qui permettent de détecter les défauts le plus tôt possible dans le cycle de développement.  Outre l’analyse statique du code, l’examen du code par les pairs, l’analyse de la couverture du code et d’autres pratiques, les tests unitaires permettent de détecter les erreurs le plus tôt possible, au moment où elles sont le moins coûteuses.

L’investissement en temps du développeur pour créer le test dans un premier temps peut être compensé par l’automatisation du processus de création.  L’essentiel est de se concentrer sur des cas d’utilisation typiques qui affectent le comportement du système.  La combinaison de « happy path » et de « edge cases » rend les tests unitaires encore plus efficaces.

Utilisés en continu dans un cycle CI/CD, les tests unitaires permettent de déterminer précisément dans quelles lignes de code se trouve le défaut.  Les bugs sont corrigés avant même qu’ils ne quittent les mains du développeur !

4. Un code ‘atomique’ propre

Plus de 90 % des coûts de développement de logiciels sont consacrés à la maintenance des systèmes existants.  La création de tests unitaires au fur et à mesure que vous développez du code améliore la conception du code et le rend plus facile à comprendre par les équipes de développement futures.  En plus d’être plus fiable, le code testé à l’unité est plus simple, plus modulaire et donc plus facilement réutilisable.  Cela permet de réduire la dette technique et de diminuer les coûts de développement à long terme.

Dans sa forme extrême, le « Test Driven Development » apporte une clarté supplémentaire même lors de la définition des prérequis en créant des tests avant le code lui-même.

5. Qu’en est-il de l’IBM i ?

Les applications IBM i modernes conçues avec une architecture ILE séparent déjà les règles de gestion, la persistance des données et l’interface utilisateur en modules ou fonctions distincts, ce qui facilite grandement l’automatisation des tests unitaires.  Les points d’entrée et de sortie d’un module sont clairs, de sorte qu’il est relativement facile de définir un état « réussite/échec ».

Cependant, de nombreuses applications sur IBM i contiennent encore des sections de code source qui ont été développées il y a 40 ans et qui sont « trop importantes pour être touchées ».  Cela crée une situation très précaire dans laquelle le risque et le coût de la refonte du code monolithique ou spaghetti en unités ou modules sont très élevés.  Oui, le prix à payer pour ne rien faire doit être dépassé par une approche plus agile.  Heureusement, les tests unitaires créent le filet de sécurité dont vous avez besoin lorsque vous modularisez votre code existant. En générant et en relançant des tests unitaires sur des applications  » back-end  » au fur et à mesure que vous les modifiez, vous vous assurez que les déploiements précédents fonctionnent toujours lorsqu’ils sont combinés à de nouvelles fonctionnalités.

Ce type de technique de « Test Driven Maintenance » (TDM) permet d’effectuer des tests unitaires à la demande et par lots, comme une sorte de système d’alerte précoce pour empêcher l’apparition de régressions lorsque vous « démêlez » votre ancien code.

Pour être pleinement adoptée par les développeurs, toute fonctionnalité de test unitaire sur IBM i doit être intégrée dans l’environnement de développement RDi, et aussi avec des outils standards tels que Jenkins et JUnit pour encourager le partage des outils entre les équipes multi-technologiques.  Les meilleures solutions de tests unitaires sur IBM i peuvent automatiser à la fois la création et l’exécution des cas de test, en utilisant la technologie d’analyse syntaxique pour rechercher les paramètres et leurs types de données et identifier rapidement toutes les entrées et sorties du programme testé.  La connaissance des références croisées et des dépendances permet également de gérer les cas de test et de réutiliser les cas entre les versions.

6. L’importance de l’automatisation des tests sur IBM i

Il existe encore quelques cas extrêmes où les applications IBM i ne peuvent pas être facilement remaniées et où le coût/temps de restructuration du code est prohibitif.

Dans ce cas, l’automatisation des tests fonctionnels est la meilleure option.  Les cas de test sont créés automatiquement lorsque les utilisateurs exécutent les fonctions de l’application à partir de l’interface utilisateur standard.  Contrairement aux tests unitaires où l’environnement de données sous-jacent est dynamique, les données de test fonctionnel sont statiques et restaurées avant chaque exécution de test afin de détecter les régressions par simple comparaison des données, sortie spool et interface utilisateur.  Il n’y a pas de notion de succès ou d’échec, seulement des différences.

Bien sûr, une stratégie de test optimale combine à la fois une automatisation des tests unitaires et des tests fonctionnels pour minimiser le temps moyen de réparation (MTTR) des défauts dans leur ensemble.  La réutilisation et le partage des cas de test évitent une perte de temps coûteuse pour le développeur et font des tests une activité continue, partie intégrante du cycle global CI/CD.

Olenka Van Schendel

WW Marketing Manager, ARCAD Software

Contactez-nous
Contactez-nous .........................................
Demandez une démo