Une architecture pour les tests automatisés

Publié le 04 novembre 2009 par Luc
Tester un logiciel demande de mettre en oeuvre une plateforme dont les buts seront de faciliter la réalisation des tests et d'assurer leur maintenance dans le temps. Il existe bien entendu plusieurs approches. En voici une adaptée aux tests automatisés.

Le principe d'une telle architecture est d'isoler les différents composant et de leur donner à chacun un rôle précis. On ajoute de plus une couche d'abstraction au dessus de l'application à tester afin de réduire l'impact sur les tests lorsque l'application est modifiée.

Cette architecture est composée des éléments suivants:

Le plan de test


Le plan de test définit la stratégie et la portée des tests. C'est le document d'entrée indispensable pour savoir ce qui est à tester, par qui, comment, quand et jusqu'à quand.

System Under Test (SUT)


C'est tout simplement l'application à tester qui peut-être éventuellement complétée par des simulateurs si l'on est en phase amont du test (tests unitaires et d'intégration).

Application Test Interface (ATI)


C'est une couche d'abstraction devant le SUT qui permet d'exécuter des actions et de récupérer les résultats. Par exemple, pour une application qui propose une page de login, l'ATI fournit dans son interface, une fonction qui implémente les actions nécessaires: la saisie d'un nom, d'un mot de passe et le click sur le bouton 'Ok' et qui permet de savoir si le login a réussi ou échoué.
L'intérêt est double: factoriser des actions et limiter l'impact sur les tests lors d'une modification de l'application. La faisabilité de création de l'ATI définit la testabilité d'un logiciel, la possibilité de le piloter et de connaître son état.

Par rapport à une approche "record & replay", c'est à dire l'enregistrement via un outil des clicks et des frappes au clavier que l'on rejoue ensuite, le temps de création des tests n'est pas plus long (grâce à la factorisation des actions) et surtout l'impact d'une modification d'IHM est limité à l'ATI. Dans le cas d'un "record & replay", il faut reprendre l'ensemble des tests.

L'ATI peut utiliser différents méthodes: simulation d'actions utilisateurs, accès direct à une base de donnée, lecture des fichiers de logs... Tous les appels au SUT faits par un test doivent être isolés dans ce composant.

L'oracle de test


Un oracle de test est un composant que l'on va soumettre aux même actions que le SUT et qui servira à définir si le résulat retourné par celui-ci est valide ou non. Un oracle peut être un logiciel très simple qui implémente les mêmes algorithmes ou bien même un produit concurrent (on trouve des exemples sur internet où Open Office est utilisé comme oracle de Microsoft Office). Il y a plusieurs types d'oracles:
  • exhaustif: l'algorithme est implémenté de manière à produire les mêmes résultats.
  • heuristique: prédit la validité sans refaire le calcul mais en vérifiant certaines caractéristiques du résultat (par exemple: pour le test d'une fonction de mise au carré, on vérifie que le résultat est positif ou nul, est supérieur à la valeur d'entrée si celle-ci est supérieure à 1...)
  • par échantillonnage: ne peut prédire la validité que sur un sous-ensemble de valeurs d'entrées connues. Il est incapable de prédire pour les autres.
  • de non-régression: prédit la validité sur la base des résultats des tests précédents.

L'oracle est un élément très important dans la stratégie de test puisqu'il définit la méthode utilisée pour s'assurer que les résultats sont corrects. Le choix de l'oracle se fait en essayant d'optimiser plusieurs éléments: la charge et le délai de développement, la capacité de trouver une méthode alternative simple pour le calcul des résultats, le besoin d'évolution des tests... Les approches peuvent être mixées pour trouver la meilleure solution pour chaque test.
Je reviendrai sur cet aspect dans un prochain article car c'est à mon avis un élément essentiel dans la mise en oeuvre d'une plateforme de tests automatisés.

Le moteur de test


C'est l'élément qui est à l'initiative de toutes les actions. Il gère le chargement des tests, leur ordonnancement et la génération au final du rapport de test. Chaque test suivra un cycle de préparation de l'environnement, de l'exécution des actions, de vérification des résultats et enfin de restauration de l'environnement. Les 2 étapes de préparation et de restauration de l'environnement sont très importantes pour permettre l'ordonnancement des tests. Il faut éviter autant que possible les dépendances entre les tests.

Le rapport de test


C'est l'élément de sortie qui indique au minimum les tests qui ont échoué et les raisons de ces erreurs. A partir de cette base, le testeur peut analyser les résultats afin d'identifier les causes et entrer, dans la base des bugs, les rapports de défaillance les plus précis possible.

Le rapport peut aussi servir à donner une image globale de la campagne des tests: taux de couverture, nombre de tests et de bugs par module... Ces informations peuvent se révéler précieuses quand on travaille de manière itérative, afin de savoir où porter en priorité l'effort sur les tests. En effet, on dit souvent que plus un module est infecté, plus il y a de chances qu'il reste des bugs non détectés.

En conclusion, cette architecture se veut modulaire afin de permettre la réutilisation de blocs et ainsi accélérer la conception des tests. Elle peut s'appliquer à tout type de logiciel à tester. Elle demande une étude fine de celui-ci afin de choisir la bonne approche pour la réalisation de l'ATI et de l'oracle qui sont les 2 éléments essentiels de cette architecture.