BT

Diffuser les Connaissances et l'Innovation dans le Développement Logiciel d'Entreprise

Contribuez

Sujets

Sélectionner votre région

Accueil InfoQ Articles Votre application est-elle prête?

Votre application est-elle prête?

Question simple, réponse difficile.

Nous déployons la plupart des logiciels à une date, et essayons avec difficulté de faire passer tous les développements et les tests en vue de cette échéance. On priorise ce qu'il nous semble important, et une fois que notre application a atteint un certain niveau de qualité, nous sommes prêts pour le déploiement. Nous avons tendance à penser qu'il y aura au moins une autre version à venir, car nous ne sommes pas toujours totalement satisfaits de ce que nous livrons. Mais même lors de la distribution, pouvons-nous définir le niveau de performance de notre application ? Nous comptons sur nos testeurs pour nous le dire, mais pour le bien du produit et sa qualité, nous devons impliquer tous les acteurs dans le processus.

Dans cette article, je vais présenter les différents aspects à tester sur les applications modernes pour en faire des applications opérationnelles. Cependant, on ne parle pas de nos efforts habituels concernant les tests! La qualité ne peut pas être corrigée à la fin. Notre objectif est de construire et d'assurer la qualité tout au long du processus de programmation.

Un bref historique des tests

Les choses étaient simples, avant d'avoir des testeurs comme groupe fonctionnel dans le projet de développement. Les développeurs faisaient que les choses fonctionnaient. Comme les projets sont devenus plus gros, les applications sont devenues plus complexes et les dates de livraison plus courtes. Comme les programmeurs étaient toujours en sous-effectif et encore plus aujourd'hui, ils ont été poussés à développer en un temps réduit, plus de fonctionnalités. Les bugs envahissaient de plus en plus le pays de la grande "Dépression de la Qualité". On a eu besoin d'exterminateurs.

Les testeurs seront ces exterminateurs. En déplaçant les responsabilités sur toute la ligne de développement, les testeurs sont devenus les gardiens empêchant les bugs de quitter leur prisons. Malheureusement, cette idée n'a pas fonctionné. Les applications étant trop complexes, les testeurs ne pouvaient pas couvrir la totalité des nombreux scénarios possibles. Même lorsque l'automatisation a été introduite, la phase de test prenait autant de temps que le développement initial. Et les bugs étaient toujours autant abondants.

Au cours des dernières années, particulièrement en parallèle avec l'expansion des méthodes agiles, il est devenu clair que les changements de l'écosystème ont rendu impossible d'effectuer en dernier la phase de test. En outre, le mouvement des logiciels basés sur le modèle client-serveur ou sur le Cloud, et les applications mobiles, ont rendu les décisions, pour définir si une application est "ready to market" ou non, beaucoup plus difficiles.

Aujourd'hui, la phase de test est complexe

Nous assimilons souvent les tests comme une étape importante dans la réalisation de logiciels opérationnels. Mais si on y réfléchit, les tests sont devenus si envahissants dans le processus de développement, qu'ils ne sont définitivement pas une "phase" ou une "activité", mais un ensemble de compétences réparties dans l'organisation du développement du produit.

Voici un simple exemple de la raison pour laquelle le test ne vérifie pas juste que quelque chose fonctionne comme il a été spécifié. Supposons que vous avez une exigence: 3 échecs de connexion à l'application bloque l'utilisateur. Cela semble assez simple, mais une fois qu'on commence à y réfléchir, on a plus de questions: Qu'est-ce-qu'un échec ? Que se passe-t-il après un "lock-out" ? Ces exigences "invisibles" peuvent ne pas être spécifiées, mais identifiées une fois que l'on comprend le contexte.

Allons un peu plus loin: nous avons figé toutes les exigences, comment toutes les tester? Vous ne pouvez pas tester directement sur le système, donc vous devrez faire vos tests fonctionnels sur un serveur de pré-production. Vous aurez besoin d'exécuter un test d'intégration qui met en place les cas de tests, exécute les étapes du scénario défini, valide les choses qui fonctionnent, et nettoie après son passage. On peut aussi tester les cas au niveau de l'unité, où on ne se soucie pas des accès au système et à la base de données.

C'est une simple exigence, et tout est fait avant que le testeur pose ses mains sur l'application.

Boucles de rétroactions

Le modèle en V est considéré comme obsolète à l'ère de l'agilité, mais aujourd'hui encore il respecte le concept fondamental qui consiste à effectuer une phase de tests pour chaque opération faisant partie des étapes du processus.

Aujourd'hui, on appelle cela des "boucles de rétroactions". Elles peuvent être décrites par le cycle Plan-Do-Check-Act de Deming:

Lors d'un développement en mode agile, on essaie de rendre ces boucles aussi courtes que possible. Le problème du modèle en cascade est que ces boucles sont énormes, le cycle de rétroaction s'étendant à des semaines, des mois, voire des années. Pourtant, tous les développeurs qui compilent leurs codes au bout de quelques minutes le savent: plus la boucle est courte - mieux c'est.

Nous avons beaucoup d'options pour invoquer ces boucles, et cela dans des situations différentes. Cependant, quand nous essayons de tester une fonctionnalité, nous sommes vite ramenés à la réalité.

Des boucles courtes ne tombent pas du ciel - nous devons les mettre en pratique et les faire fonctionner. L'intermédiaire "compile now" est rendu possible parce que:

  • Nous avons des outils qui le rendent possible. Les compilateurs sont efficaces, fournissant rapidement de nombreux commentaires.
  • Nous savons que la rétroaction fonctionne, alors nous créons un système où la rétroaction existe - nous nous sommes programmés nous-mêmes pour appuyer régulièrement sur le bouton "compile".

Cela ne fonctionne que quand le code compile relativement rapidement. Aussi efficace et léger que soit le compilateur, si la compilation prend quelques heures, ce n'est pas assez rapide. Nous ne compilons pas assez souvent, n'obtenons donc pas de rétroaction, et nous nous retrouvons à la case départ.

La rétroaction rapide grâce à l'isolement

Pour obtenir une boucle de rétroaction plus courte, nous devons arrondir les angles. Par exemple, pour éviter des cycles de compilations longs, nous pouvons compiler de manière incrémentale. Au lieu d'attendre que l'ensemble de la compilation soit terminé, nous pouvons compiler uniquement les parties modifiées. C'est la gestion du risque: nous sacrifions la qualité de la rétroaction pour sa rapidité. Il y a des chances pour que le système se comporte différemment suite à une compilation complète, mais nous supposons que les différences seront minimes. Dans cette optique, nous raccourcissons la boucle de rétroaction.

L'idée "d'isoler" des parties du systèmes et du processus pour obtenir des commentaires plus rapidement n'est pas nouvelle, et apparaît souvent au cours du développement. Nous ne pouvons pas vraiment utiliser ce terme (comme dans le cas de la compilation incrémentale), mais il est utilisé dans d'autres scénarios, pour lesquels nous voulons obtenir les informations liées aux tests plus rapidement.

Vérification et isolation

Développer la bonne application : La pire des choses est de concevoir le mauvais produit. Le développement de produits commence par identifier les bonnes exigences, bien avant d'avoir un prototype réel. Les personnes étant sur le produit utilisent toutes sortes d'outils, y compris des maquettes, des dessins, puis des prototypes pour collecter les exigences et les tests à mener - vérifient que le développement est sur la bonne voie ou sur pivot (dans le jargon du lean startup) - changent de direction - recueillent à nouveaux les informations - et enfin reviennent sur le bon chemin.

Notez que cette vérification est différente de la vérification de l'ancien modèle en V : nous vérifions que nous construisons ce dont le client a besoin, plutôt que de vérifier que les exigences spécifiées ont été construites correctement. Au départ, nous n'avons pas besoin d'une demande en direct.

Par la suite, cette collecte d'informations ne s'arrête pas. Les données utilisées continuent à être collectées sur le système, pour le développement et l'amélioration continue.

Tests unitaires fonctionnels : C'est l'exemple par excellence concernant l'utilisation de l'isolement, car la majeure partie d'une fonctionnalité ne peut pas être testée rapidement sans isolement. Que vous utilisez des frameworks de mocks, des conteneurs d'injection de dépendance, ou que vous écriviez du pur TDD et des dépendances abstraites; on en vient à l'isolation en fonction de l'environnement qu'on teste. L'idée des tests unitaires est d'obtenir une rétroactivité rapidement, il est donc logique d'utiliser des outils pour y parvenir.

En se projetant au-delà du processus de tests unitaires et de ce qu'il doit faire, on découvre que les fondements de l'isolation dans le domaine du logiciel (par exemple, en suivant les principes SOLID) apportent d'autres avantages. Nous considérons la maintenabilité d'une application comme la capacité de l'équipe de développement à ajouter des fonctionnalités, corriger des bugs ou modifier la conception. Sans le mécanisme de rétroaction rapide des tests, ces processus deviennent risqués et chronophages.

Tests d'intégration fonctionnels : Les tests unitaires sont similaires aux résultats obtenus à partir de la conception incrémentale: des retours rapides en augmentant les risques inhérents en ne testant pas complètement les flux des workflows du système. Les tests d'intégration se rapprochent plus d'une compilation complète: on a une meilleure qualité de rétroaction mais en allant plus lentement. La configuration et l'exécution des tests peuvent prendre du temps, mais ils finissent par nous donner une meilleure vue sur la performance du système.

On essaie parfois de réduire ces temps en isolant plusieurs aspects du système, afin d'accélérer la rétroaction. Donc, on pourrait empêcher le fonctionnement du navigateur et exécuter des workflows de l'interface utilisateur, et du code d'accès à la base de données. On pourrait aussi exécuter des tests sur l'interface graphique, mais sans impacter sur la base de données; jouer sur l'équilibre entre qualité et vitesse de réaction.

Les tests de communication : Même si c'est un cas particulier de tests d'intégration, les tests de communication méritent une mention spéciale, et une histoire qui leur est propre: il y a dix ans, mon équipe développait l'interface logicielle d'un gros morceau de hardware. La communication était basée sur le TCP et l'UDP. Le problème était que le matériel n'était pas encore produit. Bien sûr, on aurait pu attendre qu'il arrive, mais nous voulions avancer. Nous avons décidé de partir des informations sur les messages, la structure, les liaisons de communication et les reprises, et la gestion des erreurs d'un développement d'un simulateur de réseau. À l'époque, il n'était pas automatisé - il s'agissait d'une application qui indiquait quelles informations avaient été reçues, et qui pouvait renvoyer des messages à notre logiciel sur demande. Par la suite, nous avons ajouté une certaine automatisation de différents scénarios comme le handshaking.

Avoir un simulateur n'a pas seulement accéléré le développement et l'intégration - il nous a fait un retour sur la façon de développer les composants de communication, notifié quand quelque chose ne fonctionnait plus, et a également été utilisé comme outil de référence.

Exigences non-fonctionnelles : Il était une fois où nous avions seulement à nous soucier de la qualité. Cependant, nous avons parcouru un long chemin, et nous avons plus de choses à respecter, comme:

  • Extensibilité : Certains frameworks sont conçus pour être étendus et personnalisés. Nous fournissons habituellement des APIs aux utilisateurs qui leur permettent de rajouter les fonctionnalités que nous n'avions pas prévues. Quand nous voulons nous assurer que le système est extensible, nous mettons au point des simulateurs (et parfois de réels composants) qui utilisent l'extensibilité, et vérifient que cela fonctionne.

  • Sécurité : Parfois, on a des exigences strictes pour la sécurité, mais le plus souvent, la question sur la sécurité est traitée après coup et le renforcement à mettre en place est déterminé uniquement par le développeur. On peut évaluer les menaces à l'aide d'outils d'analyse de code statique ou par le biais d'intervenants extérieurs qui étudient l'application. Malheureusement, les analyses complètes de sécurité ne peuvent être effectuées au détriment d'environnements de production. À moins que ces environnements existent dans un cadre de scénario défini, cela signifie tests de dernière minute contre serveurs en live.

  • Scalabilité et performance : En particulier pour les serveurs d'applications, on doit évaluer la capacité de l'application à répondre non seulement aux nombreuses demandes, mais aussi sa performance lorsque les demandes augmentent. On utilise des outils de stress tests sur le système, ce qui nous offre les réponses nécessaires pour vérifier que le système fonctionne. Encore une fois, il vaut mieux savoir à l'avance, afin d'effectuer les tests sur un système isolé, plutôt que sur les serveurs, qui affectent les utilisateurs réels.

  • Disponibilité et fiabilité : La performance du système est importante, mais la disponibilité l'est tout autant pour un nombre d'utilisateurs important. De plus, on aimerait évaluer la robustesse de l'application et sa capacité à répartir après les arrêts intempestifs. On utilise les outils de stress tests pour voir ce qu'il se passe sur des serveurs isolés et obtenir les réponses de l'application aux scénarios.

  • Portabilité : Dans le monde mobile, on veut tester l'application sur plusieurs appareils. Chacun d'entre eux peut avoir un système d'exploitation, une mémoire, une résolution et une capacité différents des autres. La capacité de tester sur plusieurs appareils devient un véritable défi avec les nouveaux produits qui apparaissent sur le marché. Pendant qu'on recherche encore la façon d'être efficace sur le temps assez court dont on dispose, on se dirige vers les émulateurs. Les logiciels d'émulateurs remplacent les dispositifs physiques, et nous permettent de faire en sorte que l'application fonctionne sur plusieurs appareils.

L'expérience de l'utilisateur : Finalement, rien ne remplace l'utilisateur humain. C'est le moment où les testeurs interviennent. Les testeurs sont les représentants des consommateurs, en répondant au questions telles que: Est-ce utile ? Puis-je atteindre mes objectifs ? C'est le moment où on teste le vrai système.

Quand le reste des tests est automatisé, le manuel d'exploitation des tests est la dernière pièce du puzzle. Lorsque les testeurs approuvent, il est temps d'aller en direct.

Résumé

Le développement de produit est complexe et risqué. On veut s'assurer qu'on développe les bonnes fonctionnalités, s'assurer qu'elles fonctionnent correctement, et préparer l'application pour les échecs et les succès. En comprenant qu'une rétroaction rapide fonctionne, de plus en plus d'aspects peuvent être testés avant d'aller en direct pour répondre à notre question: Oui, c'est prêt.

À propos de l'auteur

Gil Zilberfeld a été dans le logiciel depuis son enfance. Avec vingt ans de développement de logiciels commerciaux, il a acquis une grande expérience dans les méthodologies et les pratiques logicielles. Gil est le Product Manager de Typemock, travaillant en tant que membre d'une équipe agile dans une entreprise agile, créant des outils pour des développeurs agiles. Il favorisent les tests unitaires et d'autres pratiques de conception, les méthodes agiles de bases, et d'autres outils incroyablement innovants. En plus de son mensuel en ligne webinars, Gil anime aussi des conférences internationales sur les tests unitaires, le TDD, les pratiques agiles et la communication. Pendant son temps libre, il tire sur des zombies, pour le plaisir. Le blog de Gil traite différents sujets agiles, y compris des sujets sur les processus, la communication et les tests unitaires.

Evaluer cet article

Pertinence
Style

Contenu Éducatif

BT