Le mot test est aujourd’hui très présent dans le monde professionnel ou dans la vie de tous les jours. Mais derrière ce concept structurant de l’industrie se cachent beaucoup de sens différents.
Dans cet article, nous allons revenir sur les différents types de tests, leur utilité, comment les mettre en œuvre et comment évaluer leur pertinence.
Qu’est-ce qu’un test ?
Un test logiciel est une procédure de recherche d’informations liées à la qualité d’un système (respect d’une exigence, caractéristique intrinsèque par exemple). Il est formalisé et orienté par la stratégie de test dont l'exécution est cadrée par un plan de tests.
Dans cette démarche, la certification ISTQB joue un rôle essentiel pour standardiser et professionnaliser le processus de test.
On cherche par les tests à vérifier que le système agit bien comme prévu, mais également qu’il n’existe pas de comportement problématique devant être corrigé.
En cas de correction ou de modification, les tests permettent de vérifier l’absence de “régressions” et donc de maintenir un niveau de qualité du système au moins constant tout en augmentant sa valeur.
A contrario, un test logiciel n’est pas une mesure, il répond à une question précise par oui ou non (vrai ou faux, c'est-à-dire un booléen) afin de déclencher des actions précises ou de faire un retour à l’utilisateur ou au système de supervision.
Un test passant ne veut pas dire que le logiciel fonctionne parfaitement, il valide simplement que la réponse à une assertion est vérifiée.
Pourquoi les tests logiciels ?
Les tests logiciels sont un support au processus de développement d’un logiciel ou d’un produit. Ils garantissent un ajout de valeur tout en garantissant le maintien du niveau de qualité.
Un logiciel est un ensemble complexe traduisant, par du code exécutable, des comportements, des règles, des contraintes, des intentions.
Écrire un logiciel est un processus créatif consistant à répondre à une demande de la manière la plus efficace possible en termes de ressources consommées, de complexité, de maintenabilité, et en respectant un grand nombre de critères qui en font un “bon” logiciel.
Ce processus peut également inclure l'automatisation des tests pour accélérer les livraisons et améliorer la qualité du produit logiciel.
Dans ce contexte, les tests ont trois rôles majeurs :
- Les tests logiciels sont un moyen de traduire les intentions du client dans un langage sans ambiguïté et directement lié au logiciel
- Les tests d’acceptation sont un moyen de vérifier que l’incrément de valeur demandé par le client a bien été implémenté
- Les tests de régression permettent de vérifier que le logiciel conserve dans le temps les caractéristiques qui en font un logiciel reconnu “de qualité”
Les tests logiciels permettent donc de passer la valeur de l’intention au marché et de conserver cette valeur dans le temps malgré les aléas et les changements apportés au produit.
Les différents types de tests
Pour répondre aux besoins de test d’un produit, différents types de tests sont mis en œuvre tout au long du cycle de développement du produit :
1) Les tests statiques
Des tests dits statiques, ils sont en général mis en œuvre par un analyseur de code pour valider que les blocs de code répondent à des critères précis (ou motifs). Ils répondent à des questions comme :
- Ce bloc de code possède-t-il au moins un duplicata dans le projet ?
- Ce bloc de code a-t-il la structure requise pour déclarer une fonction ?
- Ce nom de fonction répond-il à la forme attendue pour les noms de fonction ?
2) Des tests dits unitaires
Un test unitaire est un test qui ne dépend pas d’un autre test ou d’une action du système pour assurer sa fonction.
Ces tests sont souvent implémentés au plus près du code, dans le langage du logiciel lui-même, et suivent des règles bien précises.
Ils ne testent souvent qu’une seule chose pour être rapides. Un progiciel de gestion peut en contenir plus de 8000 tests.
3) Des tests de composants
Ils permettent de vérifier qu’un composant (partie isolable d’un logiciel) répond aux cas d’utilisation spécifiés par les “clients” utilisant le composant.
4) Des tests d’intégration
Ils permettent de valider la communication entre plusieurs composants selon des scénarios prédéfinis correspondants à leurs cas d’utilisation.
5) Des tests de bout en bout
Ils valident un parcours utilisateur complet, et sont parfois utilisés comme tests d’acceptation.
6) Des tests de performance
Ce sont des tests “techniques” (sécurité, accessibilité, …). Ils permettent de valider des scénarios d’utilisation en conditions réelles.
Ce type de tests permet de valider un aspect précis du logiciel vis-à-vis d’un référentiel donné.
La norme ISO-25010 présente les différents types de tests normalisés.
Méthodologie de tests, le comment
La réalisation d’un test se décompose en trois phases bien distinctes, dites 3A, pour Arrange, Act, Assert, et parfois une phase de “teardown” :
1) Arrange
Cette phase consiste à mettre en place les conditions rendant le test possible, on retrouve souvent ;
- Le déploiement
- Le chargement d’une base de données de test ou de “fixtures” (jeux de données fictifs)
- L’exécution de scripts de préparation du contexte
2) Act
Les actions réalisées par le test en lui-même.
3) Assert
4) Teardown
Lors de cette étape, non obligatoire, l’ensemble des données sont réinitialisées, les applications sont désinstallées, et les différents paramétrages sont remis à leur état initial.
Le diagramme d’état suivant résume les transitions entre les différentes étapes :
On notera qu’une fausse assertion suffira en général à rendre le test non passant.
Cependant, il existe des exceptions, parfois appelées soft assertions, dont l’état "faux" lèvera un avertissement, mais sera non bloquant pour le test.
De même, certains systèmes exécutent les boucles act/assert en parallèle, permettant ainsi de réduire fortement le temps total d’exécution d’un test.
Un exemple de mise en place
Un des exemples que l’on donne souvent pour initier une personne aux tests logiciels est le fameux “Kata” (exercice) FizzBuzz.
Dans cet exercice, on se fixe les contraintes suivantes :
- L’algorithme prend en entrée un nombre entier positif
- Si ce nombre est un multiple de 3, on retourne “Fizz”
- Si ce nombre est un multiple de 4, on retourne “Buzz”
- Dans tous les autres cas, on retournera le nombre lui-même
Exprimées sous cette forme, les exigences posent deux problèmes au développeur :
- Que faut-il retourner si le nombre est à la fois multiple de 3 et 4 ?
- Quel doit être le type de retour si le nombre n’est multiple ni de 3, ni de 4 ?
Cette situation peut donner lieu à des incompréhensions, voire même à des bugs majeurs.
Essayons donc d’utiliser les tests pour préciser un peu les choses :
La dernière contrainte peut être simplement validée en réécrivant notre premier test d’acceptation :
“Si l’entrée est un entier, alors on retournera cet entier”.
On prendra ensuite des cas précis, éventuellement indiqués par le client comme étant des cas d’utilisation réalistes :
“Si l’entrée est 0, alors on retourne le nombre entier 0”
Ce test valide une partie des spécifications, tout en précisant le type de retour, mais uniquement dans un cas précis.
On peut donc facilement écrire pour le valider :
() -> return 0
Imaginons maintenant que je souhaite prendre en compte 1 :
“Si l’entrée est 1, alors on retourne le nombre entier 1”
Il me faut donc maintenant trouver comment satisfaire les deux tests
(entier) -> return entier
Nous avons donc validé les deux tests.
On remarque que cela fonctionnera pour tous les non-multiples de 3 ou 4. Pour les multiples, nous aurons donc besoin de tests en plus qui nous guideront à la fois dans la conception, mais également pour éviter des régressions.
Nous avons donc validé notre premier test d’acceptation.
Nous pourrions ajouter à 0 et 1 les cas dits “limites”, c’est à dire des cas que le client et le testeur vont considérer comme possibles et potentiellement problématiques. Par exemple :
“Si l’entrée est 1 000 000 000 000” ou “Si l’entrée est –1” ou “Si l’entrée est 0”
Ces cas ne nécessiteront pas forcément de “code”, ils sont peut-être déjà pris en charge au niveau du langage. Par exemple, dans votre voiture, il vous est impossible de passer la vitesse “-3”, mais ne pas les oublier peut permettre d’anticiper des bugs gênants.
Les valeurs choisies dans nos cas de test (-1, 0, 1, 1 000 000) sont appelées “jeux de données de test”. Ils doivent être gérés avec rigueur, car ils sont nos hypothèses de travail. Les construire avec le client et l’équipe peut ainsi être bénéfique pour la qualité du logiciel. C’est le rôle de rituels comme le fameux “Très amigos”, ou de l’approche BDD.
La suite du travail consistera à itérer sur les tests d’acceptance jusqu’à ce que toutes les contraintes clients aient été prises en charge par des tests, et que tous les tests soient au vert. On appelle parfois cette démarche, le TDD, en français développement dirigé par les tests, parfois décliné en ATDD-TDD (avec A pour acceptance)
Une fois l’ensemble des tests passés, ils pourront être optimisés, puis intégrés dans une “intégration continue” pour permettre une recherche de régression à chaque modification du logiciel.
Les scénarios pourront ensuite être adaptés pour générer différents types de tests de performance (régime nominal, seuil critique pour le temps de réponse, …).
D’autres types de test pourront y être ajoutés (accessibilité, sécurité, déploiement, …) pour constituer une “recette” (campagne globale de tests en vue de délivrer une version) et ainsi constituer une preuve au sens de l’ISO9001. Cette preuve est en général livrée au client sous la forme d’un rapport de validation.
Template de la démarche de test logiciel
Dans ce cas pratique, nous déroulons la démarche de développement en utilisant les tests (ou TDD pour test driven development) afin de bien comprendre les étapes de déroulement et de mise au point d’un test, ainsi que son couplage avec le développement du logiciel lui-même
Télécharger cet exemple de test logiciel
Conclusion
Élément structurant du développement produit, le test logiciel est présent à chacune des phases depuis la conception et jusqu’à la réception.
Le test logiciel répond à une méthodologie précise constituée de cycles de questionnements et de construction qui permettent de faire évoluer la connaissance et la construction du logiciel pour se rapprocher petit à petit du besoin client, même si celui-ci venait à évoluer dans le temps.
C’est un outil précieux que les spécialistes du test logiciel, les testeurs, vont diffuser dans les équipes de travail afin de les aider à développer de meilleurs logiciels et à livrer des produits qui rendront leurs clients plus satisfaits.