Test de charge comme service CI pour les développeurs

Test de charge comme service CI pour les développeurs

L'un des problèmes auxquels sont souvent confrontés les fournisseurs de logiciels multi-produits est la duplication des compétences des ingénieurs — développeurs, testeurs et administrateurs d'infrastructure — dans presque chaque équipe. Cela concerne également les ingénieurs les plus coûteux — des spécialistes en test de charge.

Au lieu de se concentrer sur leurs responsabilités directes et d'utiliser leur expertise unique pour établir le processus de test de charge, choisir une méthodologie, déterminer les valeurs optimal des métriques et écrire des tests automatisés en fonction des profils de charge, les ingénieurs doivent souvent mettre en place une infrastructure de test à partir de zéro, configurer des outils de charge, les intégrer eux-mêmes dans les systèmes CI, configurer la surveillance et publier des rapports.

Des solutions à certains problèmes organisationnels de test que nous appliquons chez Positive Technologies peuvent être trouvées dans un autre article. Dans celui-ci, je vais parler de la possibilité d'intégrer les tests de charge dans un pipeline CI global grâce au concept de « load testing as a service » (tests de charge en tant que service). Vous découvrirez comment et quels images Docker des sources de charge peuvent être utilisées dans le pipeline CI ; comment connecter les sources de charge à votre projet CI à l'aide d'un modèle de construction ; à quoi ressemble un pipeline de démonstration pour l'exécution de tests de charge et la publication des résultats. Cet article peut être utile aux ingénieurs en test de logiciels et aux ingénieurs en automatisation CI qui envisagent l'architecture de leur système de charge.

L'essence du concept

Le concept de load testing as a service implique la possibilité d'intégrer les outils de charge Apache JMeter, Yandex.Tank et des frameworks propriétaires dans n'importe quel système d'intégration continue. L'exemple de démonstration sera pour GitLab CI, mais les principes énoncés sont communs à tous les systèmes CI.

Load testing as a service est un service centralisé pour effectuer des tests de charge. Les tests de charge sont exécutés dans des pools d'agents dédiés, les résultats sont publiés automatiquement dans GitLab Pages, Influx DB et Grafana ou dans des systèmes de reporting des tests (TestRail, ReportPortal, etc.). L'automatisation et l'évolutivité sont réalisées de manière très simple — en ajoutant et en paramétrant dans le projet GitLab CI un modèle standard gitlab-ci.yml.

L'avantage de cette approche réside dans le fait que l'ensemble de l'infrastructure CI, les agents de charge, les images Docker des sources de charge, les pipelines de test et la publication des rapports sont pris en charge par un département centralisé d'automatisation (les ingénieurs DevOps), tandis que les ingénieurs en test de charge peuvent se concentrer sur le développement des tests et l'analyse de leurs résultats, sans se soucier des questions d'infrastructure.

Pour simplifier, considérons que l'application cible à tester ou le serveur est déjà déployé et configuré à l'avance (des scripts automatisés en Python, SaltStack, Ansible, etc. peuvent être utilisés à cet effet). Ainsi, toute la conception du test de charge en tant que service se résume à trois étapes : préparation, test, publication des rapports. Plus de détails dans le schéma (toutes les images sont cliquables) :

Test de charge comme service CI pour les développeurs

Principes et définitions clés dans le test de charge

Lors de la réalisation de tests de charge, nous nous efforçons de suivre les normes et la méthodologie ISTQB, en utilisant la terminologie appropriée et les métriques recommandées. Voici une liste succincte des concepts et définitions clés dans le test de charge.

Agent de charge (load agent) — machine virtuelle sur laquelle l'application source de charge sera exécutée (Apache JMeter, Yandex.Tank ou un module de charge personnalisé).

Objectif du test (target) — serveur ou application installée sur le serveur qui sera soumis à la charge.

Scénario de test (test case) — ensemble d'étapes paramétrées : actions des utilisateurs et réactions attendues à ces actions, avec des requêtes et réponses réseau fixées, en fonction des paramètres définis.

Profil ou plan de charge (profile) — dans de la méthodologie ISTQB (p. 4.2.4, p. 43) les profils de charge définissent les métriques critiques pour un test spécifique et les variations possibles des paramètres de charge durant le test. Vous pouvez voir des exemples de profils sur l'image.

Test de charge comme service CI pour les développeurs

Test (test) — scénario avec un ensemble prédéfini de paramètres.

Plan de test (test-plan) — ensemble de tests et profil de charge.

Exécution du test (testrun) — une itération de l'exécution d'un test avec un scénario de charge entièrement exécuté et un rapport obtenu.

Requête réseau (request) — requête HTTP envoyée de l'agent à l'objectif.

Réponse réseau (response) — Réponse HTTP envoyée de la cible à l'agent.
Le code d'état HTTP (HTTP responses status) est un code de réponse standard du serveur d'applications.
Une transaction (transaction) est un cycle complet de « demande - réponse ». La transaction est considérée comme allant du début de l'envoi de la demande (request) à la fin de la réception de la réponse (response).

Statut de la transaction (transactions status) — indique si le cycle « demande – réponse » a été complété avec succès. Si une erreur s'est produite au cours de ce cycle, la transaction entière est considérée comme échouée.

Temps de réponse (latency) — le temps écoulé entre la fin de l'envoi de la demande (request) et le début de la réception de la réponse (response).

Métriques de charge (metrics) — caractéristiques du service chargé et de l'agent de charge, définies au cours des tests de charge.

Principales métriques pour mesurer les paramètres de charge

Certaines des métriques les plus courantes et recommandées dans la méthodologie ISTQB (p. 36, 52) sont présentées dans le tableau ci-dessous. Des métriques similaires pour l'agent et la cible sont indiquées sur une même ligne.

Métriques pour l'agent de charge
Métriques du système ou de l'application cible, testés sous charge

Le nombre  vCPU et RAM RAM,
Disque — caractéristiques matérielles de l'agent de charge
CPU, Utilisation de la mémoire, du disque — dynamique de l'utilisation du CPU, de la RAM et du disque
au cours des tests. Mesurée généralement en pourcentage des
valeurs maximales disponibles

Débit réseau (sur l'agent de charge) — la bande passante
de l'interface réseau sur le serveur
où l'agent de charge est installé.
Mesurée généralement en octets par seconde (bps)
Débit réseau(sur la cible) — bande passante de l'interface réseau
sur le serveur cible. Mesurée généralement en octets par seconde (bps)

Utilisateurs virtuels— nombre d'utilisateurs virtuels,
exécutant des scénarios de charge et
imitant les actions réelles des utilisateurs.
Statut des utilisateurs virtuels, Réussite/Échec/Total — nombre d'états de réussite et
d'échec des utilisateurs virtuels
pour les scénarios de charge, ainsi que leur nombre total.

Il est généralement attendu que tous les utilisateurs puissent accomplir
toutes leurs tâches indiquées dans le profil de charge.
Toute erreur signifiera qu'un utilisateur réel ne pourra pas
effectuer sa tâche lors de l'utilisation du système.

Requêtes par seconde (minute)— nombre de requêtes réseau par seconde (ou minute).

Caractéristique importante de l'agent de charge : combien de requêtes il peut générer.
Il s'agit en fait d'une simulation d'accès à l'application par des utilisateurs virtuels
Réponses par seconde (minute)
— le nombre de réponses réseau par seconde (ou minute).

Une caractéristique importante du service cible : combien de réponses ont été générées et envoyées aux
agents de charge
Statut des réponses HTTP

— le nombre de codes de réponse différentsdu serveur d'application, reçus par l'agent de charge.
Par exemple, 200 OK signifie un accès réussi,
et 404 indique que la ressource est introuvable
(temps de réponse) — le temps écoulé entre la fin

Latence de l'envoi de la requête (request) et le début de la réception de la réponse (response).
Il est généralement mesuré en millisecondes (ms)
Temps de réponse de la transaction

— temps d'une transaction complète,c'est-à-dire la fin du cycle « requête — réponse ».
Ce temps est mesuré depuis le début de l'envoi de la requête (request)
jusqu'à la fin de la réception de la réponse (response).
Le temps de transaction peut être mesuré en secondes (ou minutes)

de plusieurs manières : on considère le minimum,
le maximum, la moyenne et, par exemple, le 90e percentile.
Les lectures minimales et maximales représentent les états extrêmes
des performances du système.
Le 90e percentile est le plus souvent utilisé,
car il montre la majorité des utilisateurs
opérant confortablement à la limite de performance du système
Transactions par seconde (minute)

— nombre total de transactions complètes par seconde (minute),
c'est-à-dire combien l'application a pu accepter et
traiter de requêtes et délivrer de réponses.
Il s'agit en fait de la bande passante du système
Statut des transactions

, Réussi / Échoué / Total — le nombre de transactions réussies, échouées et le total.
Pour les utilisateurs réels, une transaction échouée

signifiera en fait
l'impossibilité de travailler avec le système sous charge.
Le schéma fondamental des tests de charge

Le schéma fondamental des tests de charge est très simple et se compose de trois étapes principales, que j'ai déjà mentionnées :

Préparer — Tester — Rapport , c'est-à-dire préparer les objectifs de test et définir les paramètres pour les sources de charge, puis effectuer des tests de charge et, enfin, générer et publier un rapport de test.Remarques sur le schéma :

Test de charge comme service CI pour les développeurs

QA.Tester — expert en tests de charge,

  • Cible — application cible, pour laquelle il faut connaître son comportement sous charge.
  • Classificateur des entités, étapes et actions dans le schéma

Étapes et actions

Que se passe-t-il
Que se passe-t-il
Qu'est-ce qui est en entrée
Qu'est-ce qui est en sortie

Préparer : étape de préparation au test

LoadParameters
Tâches et initialisation
par l'utilisateur
des paramètres de charge,
choix des métriques et
préparation du plan de test
(profil de charge)
Paramètres personnalisés pour
l'initialisation de l'agent de charge
Plan de test
Objectif du test

VM
Déploiement dans le cloud
d'une machine virtuelle avec
les caractéristiques requises
Paramètres VM pour l'agent de charge
Scripts d'automatisation pour
la création de VM
VM configurée dans
le cloud

Env
Configuration du système d'exploitation et préparation
de l'environnement pour
le fonctionnement de l'agent de charge
Paramètres de l'environnement pour
l'agent de charge
Scripts d'automatisation pour
paramètres de l'environnement
Environnement préparé :
OS, services et applications,
nécessaires au fonctionnement
l'agent de charge

LoadAgents
Installation, configuration et paramétrage
de l'agent de charge.
Ou téléchargement d'une image Docker avec
une source de charge préconfigurée
Image Docker de la source de charge
(JMeter, JM ou framework personnalisé)
Paramètres de configuration
l'agent de charge
Agent de charge configuré et prêt
à fonctionner

Test : étape d'exécution des tests de charge. Les sources sont des agents de charge déployés dans des pools d'agents dédiés pour GitLab CI

Charge
Démarrage de l'agent de charge
avec le plan de test sélectionné
et les paramètres de charge
Paramètres personnalisés
pour l'initialisation
l'agent de charge
Plan de test
Objectif du test
Journaux d'exécution
des tests de charge
Journaux système
Dynamique des métriques de l'objectif et de l'agent de charge

RunAgents
Exécution par l'agent
de scénarios de test
conformément à
profil de charge
Interaction de l'agent de charge
avec l'objectif de test
Plan de test
Objectif du test

Journaux
Collecte des journaux bruts
au cours des tests de charge :
enregistrements sur les actions de l'agent de charge,
l'état de l'objectif de test
et de la VM sur laquelle l'agent est exécuté

Journaux d'exécution
des tests de charge
Journaux système

Métriques
Collecte des métriques brutes au cours des tests

Dynamique des métriques de l'objectif
et de l'agent de charge

Report : étape de préparation du rapport de test

Générateur
Traitement des
métriques et journaux bruts collectés par
le système de charge et
le système de surveillance
Génération d'un rapport en
format lisible par un humain,
éventuellement avec des éléments
d'analyse
Journaux d'exécution
des tests de charge
Journaux système
Dynamique des métriques
de l'objectif et de l'agent de charge
Journaux bruts traités
dans un format compatible pour
exportation vers des stockages externes
Rapport statique sur la charge,
compatible pour analyse humaine

Publier
Publication du rapport
sur les tests de charge dans un
service externe
service
Logs «bruts» traités
dans un format approprié
pour l'exportation vers des systèmes externes
un stockage
Les rapports de charge enregistrés dans le stockage externe
sont adaptés
à l'analyse humaine
Connexion des sources de charge dans le modèle CI

Passons à la partie pratique. Je veux montrer comment, dans certains projets de l'entreprise

Positive Technologies nous avons mis en œuvre le concept de tests de charge en tant que service. Tout d'abord, nos ingénieurs DevOps ont créé dans GitLab CI un pool dédié d'agents pour exécuter des tests de charge. Pour ne pas les confondre dans les modèles avec d'autres, comme des pools de construction, nous avons ajouté des balises à ces agents,

: load. D'autres balises compréhensibles peuvent également être utilisées. Elles sont définies tagslors de l'enregistrement des GitLab CI Runners. Comment déterminer la puissance requise pour le matériel ? Les caractéristiques des agents de charge — un nombre suffisant de vCPU, RAM et Disque — peuvent être calculées en fonction du fait que l'agent doit exécuter Docker, Python (pour Yandex.Tank), l'agent GitLab CI, Java (pour Apache JMeter). Pour Java sous JMeter, il est également recommandé d'utiliser au minimum 512 Mo de RAM et, en tant que limite supérieure,

80 % de la mémoire disponible Ainsi, d'après notre expérience, nous recommandons d'utiliser au minimum pour les agents de charge : 4 vCPU, 4 Go de RAM, 60 Go de SSD. La bande passante de la carte réseau est déterminée en fonction des exigences du profil de charge..

Nous utilisons principalement deux sources de charge — des images Docker d'Apache JMeter et de Yandex.Tank.

Yandex.Tank

est un outil open-source de la société Yandex pour effectuer des tests de charge. Sa structure modulaire repose sur un générateur HTTP très performant basé sur un hit asynchrone, Phantom. Tank dispose d'un monitoring intégré des ressources du serveur testé via le protocole SSH, peut arrêter automatiquement les tests selon des conditions spécifiées, et peut afficher les résultats à la fois dans la console et sous forme de graphiques. Vous pouvez également y connecter vos propres modules pour étendre les fonctionnalités. D'ailleurs, nous avons utilisé Tank lorsque cela n'était pas encore mainstream. Dans l'article « Yandex.Tank et l'automatisation des tests de charge», vous pouvez lire l'histoire de la façon dont, en 2013, nous avons effectué des tests de charge avec son aidePT Application Firewall — l'un des produits de notre entreprise. Apache JMeter

Apache JMeter — est un outil open-source pour effectuer des tests de charge développé par Apache. Il peut être utilisé aussi bien pour tester des applications web statiques que dynamiques. JMeter prend en charge un grand nombre de protocoles et de méthodes d'interaction avec les applications : HTTP, HTTPS (Java, NodeJS, PHP, ASP.NET, etc.), services web SOAP / REST, FTP, TCP, LDAP, SMTP(S), POP3(S) et IMAP(S), bases de données via JDBC, peut exécuter des commandes shell et interagir avec des objets Java. JMeter dispose d'un IDE pour créer, déboguer et exécuter des plans de test. Il existe également un CLI pour travailler dans n'importe quel système d'exploitation compatible avec Java (Linux, Windows, Mac OS X). L'outil peut générer dynamiquement un rapport HTML sur les tests.

Pour faciliter son utilisation au sein de notre entreprise, et permettre aux testeurs de modifier et d'ajouter eux-mêmes l'environnement, nous avons créé des builds d'images Docker des sources de charge sur GitLab CI avec publication dans notre interne registre Docker sur Artifactory. Cela permet de les connecter plus rapidement et facilement dans les pipelines pour les tests de charge. Pour savoir comment effectuer un docker push dans un registre via GitLab CI, consultez des instructions.

Le fichier Docker de base pour Yandex.Tank que nous avons utilisé est le suivant :

Dockerfile 
1 | FROM direvius/yandex-tank
2 | ENTRYPOINT [""]

Et pour Apache JMeter, celui-ci :

Dockerfile 
1 | FROM vmarrazzo/jmeter
2 | ENTRYPOINT [""]

Vous pouvez lire comment notre système d'intégration continue est structuré dans l'article «Automatisation des processus de développement : comment nous avons intégré les idées DevOps chez Positive Technologies».

Modèle et pipeline

Un exemple de modèle pour effectuer des tests de charge est disponible dans le projet demo-load. Il y a fichier readme où vous pouvez lire les instructions sur l'utilisation du modèle. Dans le modèle lui-même (fichier .gitlab-ci.yml) il y a des notes sur les responsabilités de chaque étape.

Le modèle est très simple et démontre trois étapes de test de charge décrites ci-dessus dans le schéma : préparation, test et publication des rapports. Cela est géré par stages: Prepare, Test et Report.

  1. L'étape Prepare doit être utilisée pour la configuration préalable des cibles de test ou pour tester leur accessibilité. L'environnement pour les sources de charge n'a pas besoin d'être configuré, ils sont déjà préconstruits sous forme d'images Docker et publiés dans le registre Docker : il suffit d'indiquer la version souhaitée à l'étape Test. Mais il est possible de les reconstruire et de créer vos propres images modifiées.
  2. L'étape Test est utilisé pour indiquer la source de charge, lancer des tests et conserver les artefacts de test. Vous pouvez choisir n'importe quelle source de charge : Yandex.Tank, Apache JMeter, la vôtre ou toutes en même temps. Pour désactiver des sources non souhaitées, il suffit de commenter ou de supprimer le job. Points d'entrée pour les sources de charge :

    Remarque : le modèle de configuration de build est utilisé pour configurer l'interaction avec le système CI et ne doit pas contenir la logique des tests. Pour les tests, un point d'entrée est indiqué où se trouve le script bash de contrôle. La méthode de lancement des tests, la génération de rapports et les scénarios de test doivent être réalisés par les ingénieurs QA. Dans l'exemple de démonstration, pour les deux sources de charge, une requête basique à la page principale de Yandex est utilisée comme test simple. Les scénarios et les paramètres des tests se trouvent dans le répertoire .\/tests.

  3. À l'étape Rapport il est nécessaire de décrire les méthodes de publication des résultats des tests obtenus à l'étape Test dans des stockages externes, comme GitLab Pages ou des systèmes de reporting spécifiques. Pour GitLab Pages, il faut que le répertoire .\/public soit non vide à la fin des tests et contienne au moins un fichier index.html. Vous pouvez lire sur les subtilités du service GitLab Pages via le lien.

    Exemples, comment exporter des données :

    Instructions pour configurer la publication :

Dans l'exemple de démonstration, le pipeline avec des tests de charge et deux sources de charge (une peut être désactivée) ressemble à ceci :

Test de charge comme service CI pour les développeurs

Apache JMeter peut générer lui-même un rapport HTML, donc il est plus avantageux de le sauvegarder dans GitLab Pages par les moyens standards. Voici à quoi ressemble le rapport Apache JMeter :

Test de charge comme service CI pour les développeurs

Dans l'exemple de démonstration pour Yandex.Tank, vous verrez seulement un rapport textuel fictif dans la section pour GitLab Pages. Pendant le test, Tank peut enregistrer les résultats dans une base InfluxDB, et ceux-ci peuvent ensuite être affichés, par exemple, dans Grafana (la configuration se fait dans le fichier .\/tests\/example-yandextank-test.yml). Voici à quoi ressemble le rapport de Tank dans Grafana :

Test de charge comme service CI pour les développeurs

Résumé

Dans cet article, j'ai expliqué le concept de « test de charge en tant que service » (load testing as a service). L'idée principale est d'utiliser une infrastructure de pools d'agents de charge préconfigurés, des images Docker des sources de charge, des systèmes de reporting et un pipeline les unissant dans GitLab CI basé sur un modèle simple .gitlab-ci.yml (exemple via le lien). Tout cela est soutenu par une petite équipe d'ingénieurs-automatiseurs et répliqué à la demande des équipes produits. J'espère que cela vous aidera à préparer et à mettre en place un schéma similaire dans votre entreprise. Merci de votre attention !

P. S. Je tiens à remercier chaleureusement mes collègues, Sergey Kurbanov et Nikolay Yusev, pour leur aide technique dans la mise en œuvre du concept de test de charge en tant que service dans notre entreprise.

Auteur: Timur Gilmullin — directeur adjoint du département des technologies et des processus de développement (DevOps) de Positive Technologies

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster