Présentation des tests de performance
Avant-propos
Généralités
Les risques
Les enjeux des tests de performance
Les différents types de tests de performance
Bien comprendre les tests de performance
Stratégie
Identifier les scénarios critiques
Processus de campagne de performance
Méthodologie
Scripting
Modélisation
Tirs et analyses
Restitution
Avant-propos
A l'aube de l'informatique populaire et accessible à tous, l'explosion des applications a provoqué une prise de conscience par les responsables informatiques du coût de maintenance "à chaud" élevé des systèmes lorsque des erreurs graves apparaissaient en production.
Cette prise de conscience a permis de mettre en lumière la nécessité de réaliser des tests dans les phases amonts de la production pour réduire ce coût. Il existe différents types de tests : tests agile par sprint, tests d'intégration par brique ou de bout-en-bout, tests semi-automatisés ou automatisés, tests de recette fonctionnels par brique, tests métier par brique ou de bout-en bout, tests de charge et tests de performance.
Si chaque type de test permet de participer à l'effort collectif pour améliorer progressivement la qualité applicative et ainsi éviter les problèmes graves en production, seuls les tests de charge apportent une dimension multi-utilisateurs qui est aussi une des réalités de production.
En résumé, il ne suffit pas qu'une application soit exempt d'erreur pour dire qu'elle aura un véritable succès auprès des utilisateurs finaux, il faut aussi compter sur la patience de ces utilisateurs (qui est de plus en plus limitée) et donc se concentrer sur les temps de réponse vus de l’utilisateur final.
En conclusion, il n’y a pas de résultats complets ni probants si les tests de performance de sont pas accompagnés de tests de charge.
Généralités
Les tests de performance (et de charge) ont pour principal objectif la validation d'une solution logicielle et de son architecture sous-jacente liées à une utilisation simultanée multi-utilisateurs, permettant ainsi d'éviter certains problèmes en production. Ils permettent de garantir une qualité de service applicative dans des conditions réelles d'utilisation.
L'objectif des tests de performance n'est pas de couvrir 90% des cas de tests possibles et imaginables (comme les tests fonctionnels unitaires), mais de couvrir les aspects applicatifs présentant des risques systèmes en charge, des risques d'interactions avec d'autres briques applicatifs, des risques stratégiques ou financiers sur des fonctionnalités ciblées.
Les tests de performance devraient théoriquement être réalisés au plus tôt dans le cycle de développement applicatif afin de minimiser les modifications applicatives engendrées par la découverte des anomalies de performance. Ainsi, il est possible de prévoir des tests de performance en amont, dans un environnement stable (hors environnement de développement) et dans le cadre d'une démarche Agile. Dans ce cadre, les objectifs de ces tests seront alors limités : temps de réponses unitaires et/ou à faible charge, capacité de l'application à maintenir un accès concurrent multi-utilisateurs à faible charge.
Classiquement, les tests de performance sont réalisés dans un environnement de préproduction afin d'être au plus proche de la réalité techniques de production (iso architecture serveurs, chaînes de liaisons complètes, volumétrie bdd). Les résultats seront alors réellement complets et probants.
Les tests de performance permettent de déterminer des points de contention de l'architecture technique s'ils existent et de les éliminer par modifications de paramétrages techniques / tirs de charge itératifs. Ces problèmes de performance proviennent souvent, soit de l'architecture (problème de dimensionnement des machines, paramètres limites des serveurs inadaptés,...), soit d'un problème applicatif (bonnes pratiques de programmation non respectés ou inexistantes, ...). Ils permettent également de déterminer des seuils limites de bon fonctionnement (nombre d'utilisateurs, fréquence d'utilisation applicative maximum garanti,…).
Les risques
Si une application n’est pas performante, les conséquences pourraient être :
- La qualité d’accueil des clients qui se dégrade
- La perte de productivité (Traitement de dossier très long, impossibilité de déclarer des sinistres, …)
- La perte de clients
- La perte de revenu
- L’attention des médias avec, par conséquent, une perte de popularité et image de marque dégradée
- Etc.
Exemples :
- Dans une banque de finance : une anomalie de production coûte en moyenne 300 000 €.
- Chez un voyagiste : une indisponibilité d'1 minute du site web coûte 20 000 €.
Les enjeux des tests de performance
La stratégie de test dépendra en grande partie des enjeux (objectifs) des tests de performance et du contexte métier client
Exemples d’enjeux :
- Dimensionner une infrastructure de production pour un déploiement national
- Rassurer la DSI sur la montée en charge d'une application
- Valider les performances/l'endurance/la robustesse d'une application
- Comparer des solutions
- Valider que les performances ne se dégradent pas suite à une migration du socle technique et / ou applicatif
- Vérifier et/ou optimiser les performances d’une application et au besoin résoudre les problèmes de performances de cette application
- Etc.
Stratégie de tests :
La stratégie de test est la réponse au besoin de tests de performance exprimée par le client. Elle doit être adaptée au contexte d'architecture, à la réalité des flux applicatifs, au rythme et à la logique applicative (scénarios), à la volumétrie des données applicatives, à la charge applicative, au planning de campagne, à la capacité technique à faire, etc .
Pour répondre de façon appropriée aux objectifs de la campagne de performance, la stratégie s'appuie notamment sur la réalisation de certains types de tests de performance.
Les différents types de tests de performance
Test de faisabilité technique :
- Objectif : Vérifier l’éligibilité d’une application vis-à-vis de l’outillage de performance (est-ce que l’application à tester est compatible avec les outils de performance disponibles ?)
- Particularités : Ne correspond pas à un objectif client, peut être effectué en dehors de l’environnement de performance, utilisation de VM possible, vérification accès applicatif multi-utilisateurs à faible charge
Test de performance en charge nominale (pics de charge) :
- Objectif : Vérifier l'aptitude de l’application (observation technique de l'application, consommation système des serveurs applicatifs) à fonctionner dans des conditions d’utilisation « normales » (Référence : Heure la plus chargée de la journée la plus chargée de la semaine) et en « pics de charge » (Saisonnalité, exemple : attestation scolaire) par rapport aux indicateurs de production ou aux hypothèses MOE.
- Particularités : Exigences précises, vérification de la tenue en charge, peut être utilisé pour des tests de non régression ou donner des orientations de scalabilité pour les architectes, montée en charge lente.
Test de charge aux limites :
- Objectif : Déterminer les limites applicatives garanties avant une dégradation applicative importante. Cette limite est obtenue par une augmentation exponentielle de la charge bien au delà ce la charge maximum observée en production. La limite (exemple X10 la charge nominale) doit être définie pas la MOE avec l'hypothèse que les limites applicatives garanties obtenus seront inférieures à la charge de X10.
- Particularités : Exigences précises, utilisation de serveurs de même type et/ou de même dimensionnement que la cible, vérification de la tenue en charge, recherche de valeurs limites supportées par l’architecture applicative, montée en charge lente
Test de surcharge (ou de stress) :
- Objectif : Vérifier le comportement de l’application à subir une surcharge (Coefficient multiplicateur de la charge nominale doit être défini par le projet : X2 ou X4)
- Particularité : Exigences précises, utilisation de serveurs de même type et/ou de même dimensionnement que la cible, identification des éléments de la chaîne de liaison présentant des erreurs ou des temps de réponse au delà des exigences, montée en charge rapide
Test d’endurance :
- Objectif : Vérifier l'aptitude de l’application à fonctionner dans des conditions d’endurance (charge nominale sur une longue période, minimum 4 heures)
- Particularités : Exigences précises, utilisation de serveurs de même type et/ou de même dimensionnement que la cible, vérification de la tenue en charge et recherche de fuites mémoires, montée en charge lente
Test de robustesse :
- Objectif : Vérifier la tenue en charge d'un élément du système lorsque qu'il est soumis à une surcharge issue d'une défaillance d'un autre élément système (en mode dégradé, ex : arrêt d’1 serveur sur une architecture avec 2 serveurs applicatifs en Load Balancing)
- Particularités : Ces tests sont généralement pilotés par l’expertise et la production (DES), ils nécessitent des exigences précises, recherche de fuites mémoires, montée en charge lente
Bien comprendre les tests de performance
Stratégie
Tester en charge une application c'est réaliser une succession de campagnes de test de charge. Il convient de réfléchir aux objectifs de chaque campagne, de déterminer le périmètre des tests afin d'identifier les risques applicatifs à couvrir et de déterminer et valider les hypothèses de départ.
Les résultats de la campagne de tests ne sont probants que dans un contexte optimal dans un environnement matériel représentatif de celle de production ; s'il existe des serveurs physique ou virtuels en production, il convient de choisir le même type de serveur en environnement de test. Cependant, dans un souci d'économie et compte tenu d'une rapidité de mise en œuvre, une machine virtuelle peut être utilisée même si en production des serveurs physiques existent. Dans ce cas de figure, seuls les tests en charge nominaux seront probants et on vérifiera seulement les temps de réponse et si l'application fonctionne en mode multi-utilisateurs. Il ne sera pas question, par exemple, de réaliser des tests en pics de charge ou tests aux limites compte tenu des capacités de performances moindres des VM : problème de représentativité.
Outre cette nécessité de contexte iso-production, la validation applicative n'est effective que si l'ensemble des exigences de performance (en termes d'utilisateurs en charge, « fréquence » d'utilisation applicative constatée en production ou imaginée par expérience (démarche par hypothèses lorsque l'application n'existe pas en production), volumétrie en base de données, temps de réponse utilisateurs, ..) sont respectées.
Les tests de performance doivent être réalisés de façon à prendre connaissance des résultats dans leurs globalités. Si certains résultats ne sont pas conformes à ce qui est attendu, il convient de s'interroger sur la véracité de ceux-ci. S'ils se révèlent exacts, il est nécessaire de mettre en place un outil d'introspection permettant d'investiguer plus précisément les éléments de la chaine de liaison responsables de ces mauvais résultats (Ex d'outils APM : Dynatrace, AppDynamics, New Relics).
Dans le contexte d'un SI, l'application peut accéder à des services d'un prestataire externe (Cloud). Si l'objectif n'est pas de tester ces ces partenaires, il convient de mettre en place des bouchons applicatifs (virtualisation de services) qui permet de simuler de façon plus ou moins intelligente les réponses applicatives et de disposer de résultats de référence sans solliciter ce prestataire et sans attendre que ces services soient opérationnels.
Identifier les scénarios critiques
Il est très important d'identifier les scénarios pertinents.
Pour définir ces scénarios, on peut :
- Récupérer les statistiques de l'utilisation de l'application si elles existent (par exemple le nombre quotidien ou mensuel de transactions « métier », l'analyse des statistiques Web (access_log), etc.)
- Si l'application n'est pas encore en production, le projet doit émettre des hypothèses qui permettra de définir une charge applicative nominale
- Définir avec le projet les scénarios majeurs d'utilisation (les fonctions les plus utilisées, les plus avancées ou les plus consommatrices) de leur application (suites d'écrans et nombre d'utilisateurs).
Ces scénarios devront être :
- Réalistes au niveau des tests de performance (écrans consultés, champs saisis dans les formulaires, temps entre chaque action, etc...)
Il y a trois types de scénarios à prendre en compte :
- Fréquents : Les scénarios du quotidien (Exemple : les recherches, les consultations d’un sociétaire)
- Vitaux : Les scénarios qui sont vitaux (Exemple : l’affectation des tâches aux gestionnaires, le déclenchement de la paye)
- Risqués : Les scénarios risqués d’un point de vue performance pour l’application (Exemple : l’accès à la GED, une recherche complexe, la génération de document)
Processus de campagne de performance
Le processus de campagne de performance se défini par la réalisation des 4 phases ci-dessous.
Méthodologie
La méthodologie repose sur un ensemble de documents permettant de définir l'ensemble des éléments nécessaires à sa réalisation, d'exposer les résultats d'analyses et de donner le bilan de la campagne.
Les documents sont : Besoins de tests, Plan de tests, Rapports de tests, Retour d'expérience, Bilan de campagne, …
Etape 1 : Définition du Besoin de tests :
- Définir les objectifs de la campagne,
- Définir le planning de la campagne,
- Définir le périmètre fonctionnel,
- Définir l'architecture technique,
- Définir les exigences,
- Définir le jeu de données,
- Définir les scénarios fonctionnels,
- Définir les types de tests de performance,
- Définir les modélisations de charge,
- Définir les actions pré et post tests de charge
- Définir la volumétrie
- …
Etape 2 : Réalisation :
- Enregistrer une cinématique fonctionnelle à l'aide d'un outil de scripting (cf § Scripting),
- Déterminer plusieurs modélisations de charge de cette cinématique fonctionnelle (cf § Modélisation),
- Exécuter un test de charge préliminaire (de validation script / scénario de charge),
- Exécuter les tirs de charge,
- Analyser les résultats,
- Relancer les tirs de charge après ajustement,
- Rédiger des rapports Flash et Point de situation
Etape 3 : Restitution :
- Rédiger le Rapport de Tests de la campagne
- Rédiger le Bilan des tests de charge
- Rédiger un retour d'expérience (le cas échéant)
Scripting
Les tests de performance sont réalisés à l'aide d'outils capables de simuler des utilisateurs virtuels. L'opération de scripting est une opération permettant la transformation d'une capture de l'application en un script (en langage de programmation ou dans des IHM).
Au préalable, le document besoin des tests de performance contient l'ensemble des scénarios fonctionnels (sous forme de captures d'écran de l'application) qu'il faut scripter. Pour être valables, ces scénarios fonctionnels doivent respecter des conditions de rejouabilité (ex : création de contrats en masse donc nécessité d'une restauration des bases pour revenir à état initial), de cohérence (connexion suivi d'une déconnexion), de réalisme (certaines fonctionnalités ne sont jamais utilisées d'une certaine façon mais toujours d'une autre) mais aussi de compatibilité avec les outils de scripting (toutes les applications ne sont scriptables). Pour ce dernier point, il convient donc de réaliser dès le début du projet un test de faisabilité technique lorsqu'un doute d'adhérence technique est émis entre les outils de scripting et la technique utilisée dans l'application.
Suite à la phase d'enregistrement, le script créé avec un utilisateur applicatif n'est pas rejouable en l'état. Il faut réaliser une corrélation qui consiste à assurer la cohérence des enchaînements d'appels des pages applicatives (Id de sessions entre pages web, paramètres d'entrée issus des paramètres de sortie des pages précédentes, …). Il faut ensuite variabiliser le script avec le jeu de données (liste des users, cas de tests applicatifs).
La dernière phase consiste à encapsuler chaque appel applicatif par des transactions. Ce sont les résultats de ces transactions qui seront visibles dans les analyses et dans les résultats. Il faut aussi considérer les temps de réflexion des utilisateurs entre deux actions utilisateurs (un temps nul entre deux appels applicatifs n'est pas réaliste dans la majorité des cas).
Modélisation
Il existe plusieurs types de modélisation de charge qui représente graphiquement et temporellement tous les type de tests de performance dont nous avons parlé précédemment.
La modélisation repose souvent sur une connaissance de l'activité réelle en production. Le modèle de charge pour le type "charge nominale" est la représentation de la charge maximum constatée en production. Le modèle le plus commun est le modèle dit en « M ». Ce modèle présente la particularité de dessiner un M sur une activité d'une journée où les deux pointes du M sont les deux maximums de la journée (souvent entre 10 heures et 12 heures et entre 14 heures et 16 heures). Cependant, il est courant d'utiliser une représentation théorique et simple de ce modèle avec une montée en charge (à la charge maximum), un plateau de charge (d'une charge constante) et une descente de charge rapide.
Tirs et analyses
Les tirs représentent l'exécution de de tous les éléments conçus préalablement : Scripting, modélisation, Jdd, monitoring. Pendant ces tirs, il s'agit d'observer le comportement de l'application : erreurs dans les logs applicatifs, erreurs dans les outils de performance, consommation des serveurs, temps de réponse. Post tir, des outils d'APM vont permettre d'observer le comportement de l'application, de son architecture, des points de contention, etc... . D'autres outils permettent d'observer les métriques systèmes de façon précise et le comportement au cœur de l'application (JVM pour Java ou Framework .NET) tels que Grafana.
Restitution
Lorsque la campagne de tests est réputée terminée, il est nécessaire de rédiger un rapport pour la campagne de tests de performance.
Dans ce rapport, il faut consigner les éléments suivants (dans l'ordre) :
- Rappel du contexte applicatif
- Conclusion de la campagne
- Rappel des exigences
- Préconisations pour la mise en production
- Réserves vis à vis des éléments en erreurs ou des éléments non testés (couverture de tests non optimale)
- Analyses détaillées de tous les tirs probants avec conclusion pour chaque tirs et graphes détaillées
- Annexes avec des éléments complémentaires (graphes, éléments d'architecture applicative, etc...)
Co-rédigé par Philippe Naveau et Marc Tuffreau