Tests de charge vs tests de contrainte : Différences, métriques et exemples k6
Cela prouve que votre système gère le trafic que vous attendez. L’autre découvre où il se brise et comment il récupère. Apprenez quand exécuter chacun d’eux, à quels chiffres se fier et comment planifier un test qui donne de vraies réponses.
- Les Tests de charge vérifient qu’un système atteint ses objectifs dans le cadre du trafic attendu.
- Les tests de résistance dépassent les capacités pour trouver le point de rupture et étudier la récupération.
- Les outils sont généralement les mêmes. Ce qui diffère, c’est l’objectif et le modèle de trafic.
- Jugez les résultats avec des centiles tels que p95 et p99, car les moyennes peuvent cacher de graves problèmes.
Votre application fonctionne parfaitement avec dix utilisateurs. Que se passe-t-il le jour de la vente, avec dix mille ? Tests de charge vs tests de stress décrit deux manières différentes de répondre à cette question, et les mélanger conduit à des tests qui ne prouvent pas ce que vous pensez qu’ils font.
Ce guide explique ce que chacun montre, les types de tests associés et comment lire les résultats. Nous avons effectué le calcul du petit centile ci-dessous sur Python 3.13, avec des nombres simulés. Les scripts k6 sont des exemples illustratifs que nous n’avons pas exécutés, et les comptes d’utilisateurs et les cibles sont inventés, alors remplacez-les par les vôtres. Exécutez ces tests uniquement sur les systèmes que vous possédez ou que vous êtes autorisé à tester, car un trafic important peut ressembler à une attaque et provoquer de véritables pannes.
La réponse courte
Un test de charge demande : pouvons-nous gérer le trafic auquel nous nous attendons et atteindre nos objectifs en le faisant ? Un stress test pose la question suivante : combien pouvons-nous prendre avant d’échouer, comment échouons-nous et à quelle vitesse pouvons-nous nous rétablir ?
Pensez à un pont. Un test de charge fait circuler le nombre prévu de camions et confirme que tout va bien. Un test de résistance continue d’ajouter du poids pour connaître sa limite et savoir s’il donne un avertissement en premier. Heureusement, un logiciel coûte moins cher à briser qu’un pont.
Tests de charge et tests de contrainte côte à côte
| Aspect | Test de charge | Tests de résistance |
|---|---|---|
| Question principale | Atteignons-nous les objectifs à la charge prévue ? | Où et comment fait-on une pause ? |
| Niveau de trafic | Pic normal à attendu | Au-delà du pic attendu |
| Modèle | Accélérez, restez stable | Continuer à augmenter jusqu’à l’échec |
| Échec | Un test raté | Le résultat attendu |
| Indicateurs clés | Temps de réponse, débit, erreurs | Point de rupture, mode de défaillance, temps de récupération |
| Calendrier typique | Avant chaque sortie ou événement majeur | Une fois que le système est stable sous charge |
| Résultat | Réussir ou échouer contre les cibles | Une limite de capacité et une liste de points faibles |
Qu’est-ce que le test de charge ?
Les tests de charge simulent le trafic réaliste auquel vous vous attendez et mesurent le comportement du système. Il a besoin d’un objectif de test, par exemple : « avec 500 utilisateurs simultanés, 95 % des demandes de paiement se terminent dans un délai de 800 ms, avec moins de 1 % d’erreurs. »
Voici à quoi cela pourrait ressembler en tant que script k6. Les tests k6 sont écrits en JavaScript et thresholds transforment vos objectifs en résultat de réussite ou d’échec :
import http from "k6/http";
import { sleep } from "k6";
export const options = {
stages: [
{ duration: "5m", target: 500 }, // ramp up
{ duration: "20m", target: 500 }, // hold at expected peak
{ duration: "2m", target: 0 }, // ramp down
],
thresholds: {
http_req_duration: ["p(95)<800"],
http_req_failed: ["rate<0.01"],
},
};
export default function () {
http.get("https://staging.example.com/products");
sleep(1); // think time, as real users pause
}
Le sleep compte. Sans temps de réflexion, chaque utilisateur virtuel martèle continuellement le serveur, générant bien plus de trafic que ne le ferait le même nombre de personnes réelles.
Qu’est-ce que les tests de résistance ?
Les tests de résistance vont délibérément au-delà des niveaux attendus. Vous n’essayez pas de réussir. Vous voulez des réponses à des questions telles que :
- À quel niveau les performances commencent-elles à s’effondrer ?
- Quel composant tombe en panne en premier : la base de données, les serveurs d’applications ou un appel tiers ?
- Est-ce qu’il échoue normalement avec des erreurs claires, ou est-ce qu’il plante et perd des données ?
- Est-ce qu’il se rétablit tout seul lorsque le trafic baisse ?
export const options = {
stages: [
{ duration: "5m", target: 500 }, // expected peak
{ duration: "5m", target: 1000 }, // beyond it
{ duration: "5m", target: 2000 }, // further
{ duration: "5m", target: 4000 }, // likely to break
{ duration: "10m", target: 0 }, // recovery: does it come back?
],
};
Cette dernière étape de récupération est souvent oubliée, et elle est peut-être la plus précieuse. Un système qui gère bien les pannes mais ne se rétablit jamais sans un redémarrage manuel signifie toujours une panne que quelqu’un doit réparer au milieu de la nuit. Idéalement, sous une charge extrême, un système devrait abandonner le travail de manière contrôlée, en renvoyant des 503 réponses claires au lieu d’expirer.
Spike, trempage et autres types
Les tests de charge et de contrainte appartiennent à une famille plus large de tests de performances :
| Tapez | Modèle | Ce qu’il trouve |
|---|---|---|
| Fumée (performance) | Quelques utilisateurs, brièvement | Si le script et le système fonctionnent du tout |
| Charger | Pic attendu, tenu | Si les objectifs sont atteints |
| Stress | Dépassement de capacité | Limites et modes de défaillance |
| Pointe | Un saut soudain, puis une chute | Comportement de mise à l’échelle automatique et de file d’attente |
| Trempage (endurance) | Charge normale pendant des heures | Fuites de mémoire, connexions épuisées |
| Capacité | Augmentation progressive | La charge maximale dans vos objectifs |
Les tests d’immersion détectent des problèmes que les tests courts ne détectent jamais. Une petite fuite de mémoire peut sembler inoffensive pendant vingt minutes et n’interrompre le service qu’au bout de deux jours. Les tests Spike conviennent à des événements tels que les ventes flash, où le trafic ne se développe pas progressivement.
Des indicateurs qui comptent
| Métrique | Signification | Surveillez |
|---|---|---|
| Temps de réponse (percentiles) | Combien de temps prennent les demandes | p95 et p99 en hausse |
| Débit | Requêtes traitées par seconde | Aplatissement à mesure que le nombre d’utilisateurs augmente |
| Taux d’erreur | Pourcentage de demandes ayant échoué | Toute hausse soudaine |
| Processeur et mémoire | Utilisation des ressources du serveur | Saturation, ou croissance régulière |
| Base de données | Requêtes lentes, utilisation du pool de connexions | Épuisement de la piscine, le verrou attend |
| Profondeur de la file d’attente | Travaux en attente de traitement | Une croissance qui ne s’épuise jamais |
Pourquoi les moyennes sont trompeuses
Les moyennes cachent la lenteur des requêtes dont se plaignent les vraies personnes. Pour le montrer, nous avons généré 100 temps de réponse simulés, dont 95 étaient rapides (80 à 200 ms) et 5 très lents (2,5 à 4 secondes), puis avons calculé les statistiques communes :
import math, random, statistics
random.seed(3)
times = [random.randint(80, 200) for _ in range(95)] \
+ [random.randint(2500, 4000) for _ in range(5)]
def pct(values, p):
values = sorted(values)
return values[math.ceil(p / 100 * len(values)) - 1]
print("avg", round(statistics.mean(times)), "p50", pct(times, 50),
"p95", pct(times, 95), "p99", pct(times, 99), "max", max(times))
# avg 302 p50 150 p95 199 p99 3740 max 3896
Regardez attentivement ces chiffres. La moyenne de 302 ms ne décrit personne. Les requêtes typiques prenaient environ 150 ms, tandis que les requêtes lentes prenaient plus de 3 secondes. Même p95 semble sain à 199 ms, et seul p99 révèle le problème. Un chiffre comme p95 signifie que 95 % des requêtes ont été aussi rapides ou plus rapides.
Et un pour cent des demandes n’est pas un événement rare. Si une page effectue 50 requêtes, un p99 lent affecte une grande partie des pages vues. Fixez des objectifs sur les percentiles qui comptent pour vous et examinez-en plusieurs ensemble.
Conseil : Recherchez le « genou » dans vos graphiques. À mesure que la charge augmente, les temps de réponse restent stables pendant un certain temps, puis augmentent soudainement, tandis que le débit cesse de croître. Ce point dépend de votre capacité pratique, et il arrive souvent bien avant que quoi que ce soit ne plante réellement.
Outils
| Outil | Script | Connu pour |
|---|---|---|
| k6 | Javascript | Conviviaux pour les développeurs, les seuils conviennent à CI |
| JMètre | Interface graphique et XML | Mature, prend en charge de nombreux protocoles |
| Gatling | Scala, Java, Kotlin et autres | Basé sur du code, efficace |
| Criquet | Python | Comportement utilisateur simple, basé sur Python |
N’importe lequel d’entre eux peut exécuter à la fois des tests de charge et de stress. Choisissez celui qui correspond aux compétences de votre équipe, plutôt que de courir après une liste de fonctionnalités. Pour en utiliser un dans votre pipeline, consultez qu’est-ce que CI/CD.
Comment planifier un test
- Fixez-vous des objectifs. Utilisez de véritables analyses pour déterminer votre pic de trafic et définir des cibles.
- Choisissez des parcours. Modélisez un comportement réaliste des utilisateurs, tel que la navigation, la recherche et le paiement, dans des proportions réalistes. Frapper uniquement la page d’accueil ne prouve pas grand-chose.
- Utilisez un environnement réaliste. Un petit serveur intermédiaire ne peut pas prédire la production. Notez toutes les différences.
- Préparez les données. Utilisez des volumes réalistes, car une requête rapide sur 100 lignes peut en explorer 10 millions.
- Avertissez les gens. Informez votre équipe opérationnelle et tout tiers, et ne testez pas de charge un fournisseur de paiement par accident. Moquez-vous des services externes le cas échéant.
- Commencez petit. Exécutez d’abord un petit test de fumée pour confirmer que votre script fonctionne.
- Surveillez tout. Sans les métriques du serveur, vous verrez que il a ralenti, mais pas pourquoi.
- Répétez. Exécutez-le à nouveau après chaque correctif et conservez une base de référence à laquelle comparer.
Lire les résultats
| Symptôme | Cause possible |
|---|---|
| Réponses lentes, mais processeur faible | En attente d’une base de données, d’un verrou ou d’un service externe |
| Le processeur de la base de données est élevé | Index manquants ou requêtes inefficaces |
| Erreurs de connexion soudaines | Pool de connexions ou limite de fichiers atteinte |
| La mémoire grimpe régulièrement | Une fuite ou un cache illimité |
| Le processeur du générateur de charge est élevé | L’outil de test est le goulot d’étranglement, pas votre système |
Les bases de données constituent un goulot d’étranglement courant. Si les requêtes constituent le problème, lisez notre guide sur l’optimisation des requêtes SQL. Cette dernière ligne du tableau est un piège important : vérifiez toujours également l’état de la machine générant la charge.
Erreurs courantes
- Confondre les utilisateurs avec les requêtes. Indiquez clairement si une cible signifie des utilisateurs simultanés ou des requêtes par seconde.
- Laisser de côté le temps de réflexion. Cela gonfle le trafic et donne des résultats trompeurs.
- Tests trop tardifs. Une semaine avant le lancement ne laisse pas le temps de résoudre les problèmes d’architecture.
- Utilisation d’un seul point de terminaison. Le trafic réel mélange les lectures, les écritures et les recherches.
- La mise en cache cache tout. Des requêtes répétées identiques peuvent uniquement tester votre cache, alors faites varier les données.
- Test une fois. Les performances changent à chaque version, alors exécutez des tests régulièrement.
Pour conclure
Exécutez des tests de charge pour confirmer que vous pouvez gérer le trafic que vous attendez, et des tests de résistance pour savoir ce qui se passe lorsque vous ne le pouvez pas. Commencez petit : choisissez votre parcours utilisateur le plus important, définissez un objectif clair et exécutez un court test par rapport à la mise en scène avec la surveillance activée. Cette première exécution vous apprend généralement quelque chose et vous pouvez construire à partir de là.
Questions fréquentes
Quelle est la principale différence entre les tests de charge et de stress ?
Les tests de charge vérifient le comportement du trafic attendu par rapport aux objectifs définis. Les tests de résistance vont au-delà de la capacité à trouver le point de rupture et la manière dont le système se rétablit.
Dois-je d’abord exécuter des tests de charge ou des tests de résistance ?
Testez d’abord la charge. Une fois que le système atteint ses objectifs dans le cadre du trafic prévu, effectuez des tests de résistance pour explorer ses limites. Les résultats de stress signifient peu sur un système instable.
Quelle est la différence entre un test de stress et un test de pointe ?
Un test de résistance augmente généralement la charge étape par étape jusqu’à la défaillance. Un test de pointe passe soudainement à un niveau élevé, pour voir comment le système fait face à un changement brusque.
Quel est le temps de réponse p95 ?
Cela signifie que 95 % des demandes sont terminées à ce moment-là ou en dessous. Il décrit mieux l’expérience de la plupart des utilisateurs que la moyenne.
Puis-je exécuter des tests de charge en production ?
Vous pouvez le faire, mais avec précaution, avec la permission, la surveillance et un moyen de vous arrêter rapidement. La plupart des équipes commencent par un environnement de simulation de type production afin de réduire les risques pour les utilisateurs réels.
Continuez à apprendre
Besoin d’aide pour les tests, WordPress ou le référencement ?
Nous aidons les équipes à proposer de meilleurs logiciels et à développer leurs sites. Dites-nous sur quoi vous travaillez et nous vous proposerons une prochaine étape claire.
Plus de guides sur tests, IA et développement moderne
Vous avez apprécié cet article ? Choisissez un sujet et accédez directement à nos nouveaux didacticiels.
Les hallucinations de l'IA expliquées : pourquoi les modèles de langage inventent les choses et comment les réduire
Les hallucinations de l'IA ont expliqué : ce qu'elles sont, pourquoi les modèles de langage les produisent, les types courants, comment les réduire …
Lire l'article →DevOpsVariables d'environnement expliquées : fichiers .env, secrets et configuration correctement effectués
Variables d'environnement expliquées avec des exemples Python que nous avons exécutés : lecture et définition, pourquoi chaque valeur est une chaîne…
Lire l'article →Développement logicielLimitation du débit de l'API expliquée : algorithmes, en-têtes et gestion des erreurs 429
Limitation du débit de l'API expliquée avec une simulation que nous avons exécutée : compartiment de jetons, fenêtre fixe, fenêtre glissante, 429 ré…
Lire l'article →Automatisation des testsSe moquer en Python : unittest.mock, patch et les erreurs qui font mentir les tests
Moquerie en Python avec unittest.mock, testée : Mock et return_value, side_effect, correctifs où un nom est utilisé, spec et autospec, dates moqueus…
Lire l'article →Tests logicielsCouverture du code expliquée : couverture des lignes par rapport aux branches et ce que signifie réellement 100 %
Couverture du code expliquée avec une véritable exécution de cover.py : couverture des lignes, des branches et des conditions, lecture d'un rapport,…
Lire l'article →Bases de données et SQLDELETE vs TRUNCATE vs DROP dans SQL : différences, restauration et quand les utiliser
DELETE vs TRUNCATE vs DROP expliqué avec SQL testé : ce que chacun supprime, restauration, déclencheurs, réinitialisation d'identité, vitesse et en …
Lire l'article →Bases de données et SQLVues SQL expliquées : créez, utilisez et évitez les pièges, avec des exemples
Vues SQL expliquées avec les requêtes que nous avons exécutées : création d'une vue, résultats en direct, masquage des colonnes, performances, vues …
Lire l'article →Développement logicielInterface TypeScript vs Type : différences réelles, testées avec le compilateur
Interface TypeScript vs type, vérifiée avec le vrai compilateur : ce que les deux peuvent faire, ce qu'un seul peut faire, la fusion des déclaration…
Lire l'article →Développement logicielPython *args et **kwargs expliqués : fonctions flexibles avec des exemples clairs
Python *args et **kwargs expliqués avec le code que nous avons exécuté : emballage et déballage, ordre des paramètres, arguments de mot-clé uniqueme…
Lire l'article →Développement logicielFonctions Python Lambda : syntaxe, utilisations réelles et quand ne pas les utiliser
Fonctions Python lambda expliquées avec le code que nous avons exécuté : syntaxe, tri avec clé, carte et filtre, fermetures, piège de liaison tardiv…
Lire l'article →Intelligence artificielleQue sont les agents IA ? Comment ils fonctionnent, avec une simple boucle d'agent que vous pouvez exécuter
Que sont les agents IA ? Un guide simple sur la boucle d'agent, les outils, la mémoire et les garde-fous, avec une petite boucle Python que nous avo…
Lire l'article →DevOpsSurveillance vs observabilité : la vraie différence, avec les journaux, les métriques et les traces
Surveillance et observabilité expliquées : échecs connus et inconnus, journaux, métriques et traces, présentation pas à pas des incidents de paiemen…
Lire l'article →DevOpsVolumes Docker vs montages Bind : conserver les données du conteneur de la bonne manière
Volumes Docker et montages de liaison expliqués : pourquoi les données du conteneur disparaissent, volumes nommés, montages de liaison, tmpfs, exemp…
Lire l'article →Automatisation des testsTDD vs BDD : principales différences, une fonctionnalité conçue dans les deux sens et quand les utiliser
TDD vs BDD expliqué avec une fonctionnalité de remise construite dans les deux sens : refactor rouge-vert avec le code que nous avons exécuté, scéna…
Lire l'article →Tests logicielsTests d'acceptation utilisateur (UAT) : processus, liste de contrôle et exemples réels
Les tests d'acceptation des utilisateurs sont expliqués : qui les exécute, en quoi ils diffèrent du contrôle qualité, un processus en sept étapes, u…
Lire l'article →Bases de données et SQLExplication des valeurs SQL NULL : IS NULL, COALESCE, NULLIF et les pièges à éviter
Les valeurs SQL NULL expliquées avec les requêtes que nous avons exécutées : logique à trois valeurs, IS NULL, COALESCE, NULLIF, comment les agrégat…
Lire l'article →Bases de données et SQLInstruction SQL CASE WHEN : syntaxe, exemples réels et erreurs courantes
SQL CASE WHEN expliqué avec les requêtes que nous avons exécutées : formulaires simples et recherchés, ordre des conditions, pivots avec SUM, astuce…
Lire l'article →Développement logicielQu'est-ce que JWT ? Les jetons Web JSON expliqués avec un exemple fonctionnel
Qu’est-ce que JWT ? JSON Web Tokens expliqué : les trois parties, un jeton construit et falsifié dans le code que nous avons exécuté, JWT vs session…
Lire l'article →Développement logicielBoucle d'événements JavaScript expliquée : pile d'appels, microtâches et minuteries avec des exemples
La boucle d'événements JavaScript expliquée avec le code que nous avons exécuté : pile d'appels, files d'attente de tâches et de microtâches, pourqu…
Lire l'article →Développement logicielGénérateurs Python et rendement expliqués : économisez de la mémoire avec des exemples réels
Les générateurs Python et le rendement expliqués avec le code que nous avons exécuté : comment ils s'arrêtent et reprennent, les économies de mémoir…
Lire l'article →Intelligence artificielleQue sont les intégrations ? Vecteurs et similarité cosinus expliqués simplement
Que sont les intégrations ? Un guide en langage simple sur les vecteurs, la similarité cosinus et la recherche sémantique, avec un petit exemple que…
Lire l'article →DevOpsDéploiement Bleu-Vert vs Canary : différences, compromis et comment choisir
Explication du déploiement bleu-vert ou canari : comment chacun fonctionne, coût, risque et restauration, regroupement d'utilisateurs stable que nou…
Lire l'article →Automatisation des testsTests instables : quelles sont leurs causes et comment les corriger définitivement
Des tests irréguliers expliqués avec des démos que nous avons exécutées : les principales causes, comment en confirmer et en diagnostiquer une, les …
Lire l'article →Tests logicielsTests de charge vs tests de contrainte : différences, métriques et exemples k6
Explication des tests de charge et des tests de stress : ce que chacun prouve, les tests de pointe et de trempage, les métriques qui comptent, pourq…
Lire l'article →Tests logicielsScénario de test et scénario de test : principales différences, exemples et quand les utiliser
Scénario de test et scénario de test expliqués : des définitions claires, un tableau côte à côte, une fonctionnalité de réinitialisation de mot de p…
Lire l'article →Bases de données et SQLOptimisation des requêtes SQL : lire les plans d'exécution et corriger les requêtes lentes, avec des délais
Optimisation des requêtes SQL testée sur un million de lignes : lire les plans d'exécution, ajouter les bons index, corriger les filtres non Sargabl…
Lire l'article →Bases de données et SQLSQL UNION vs UNION ALL : différences, exemples et performances testées
SQL UNION vs UNION ALL expliqué avec les requêtes que nous avons exécutées : des doublons, les règles suivent toutes les deux, un véritable bug de d…
Lire l'article →Développement logicielTutoriel API JavaScript Fetch : GET, POST, gestion des erreurs et délais d'attente
Un didacticiel de l'API JavaScript Fetch testé sur un serveur local : GET et POST, pourquoi 404 ne lance pas, un assistant réutilisable, des chaînes…
Lire l'article →Développement logicielGestion des fichiers Python : lecture, écriture, CSV, JSON et pathlib avec exemples
Gestion des fichiers Python expliquée avec le code que nous avons exécuté : modes ouverts, avec lecture de fichiers volumineux, CSV, JSON, pathlib, …
Lire l'article →Développement logicielClasses et objets Python : didacticiel POO avec des exemples réels
Classes et objets Python expliqués avec le code que nous avons exécuté : __init__, méthodes, attributs de classe par rapport à l'instance, héritage,…
Lire l'article →Intelligence artificielleQu'est-ce qu'un grand modèle de langage ? Comment fonctionnent les LLM, expliqués sans battage médiatique
Qu’est-ce qu’un grand modèle de langage ? Les LLM expliqués en langage simple : jetons, intégrations, attention, formation, fenêtres de température …
Lire l'article →DevOpsCommandes Linux pour les débutants : le guide du terminal essentiel avec des exemples
Commandes Linux pour débutants, regroupées par tâche : navigation, fichiers, affichage des journaux, grep, tuyaux, autorisations, processus et archi…
Lire l'article →Automatisation des testsSelenium vs Playwright : principales différences, code comparé et lequel choisir
Comparatif Selenium vs Playwright : architecture, attente, support du navigateur et du langage, débogage, même test dans les deux outils, conseils d…
Lire l'article →Tests logicielsPartitionnement d'équivalence : technique de conception de tests expliquée avec des exemples concrets
Le partitionnement d'équivalence expliqué : comment trouver des partitions valides et invalides, des exemples concrets d'âges, de mots de passe et d…
Lire l'article →Tests logicielsGravité vs priorité dans les tests logiciels : différences, matrice et exemples réels
Explication de la gravité et de la priorité dans les tests logiciels : des définitions claires, une matrice à quatre voies avec des exemples, des éc…
Lire l'article →Bases de données et SQLTutoriel sur les sous-requêtes SQL : types, sous-requêtes corrélées et EXISTE avec des exemples
Un didacticiel sur les sous-requêtes SQL avec les requêtes que nous avons exécutées : les sous-requêtes scalaires, IN, FROM et SELECT, les sous-requ…
Lire l'article →Bases de données et SQLTransactions SQL et ACID expliquées : COMMIT, ROLLBACK et niveaux d'isolement
Transactions SQL et ACID expliquées avec un virement bancaire que nous avons effectué : COMMIT, ROLLBACK, points de sauvegarde, verrous, niveaux d'i…
Lire l'article →Développement logicielGit merge vs rebase : différences, exemples et quand utiliser chacun
Git merge vs rebase expliqué avec de vraies sorties de log, un tableau comparatif, la règle d'or du rebase et un flux de travail sûr pour les équipes.
Lire l'article →Développement logicielList comprehension Python : syntaxe, exemples et cas à éviter
La list comprehension Python expliquée : syntaxe, filtres, if-else, boucles imbriquées, temps mesurés et cas où une boucle for classique est préféra…
Lire l'article →Bases de données et SQLJointures SQL expliquées avec exemples (Inner, Left, Right, Full)
Comprenez les jointures SQL pas à pas avec des tables et requêtes d'exemple : INNER, LEFT, RIGHT, FULL, CROSS et SELF, plus erreurs courantes et con…
Lire l'article →