Cherchez « modèle de rapport de bug » et vous trouverez cent variantes du même formulaire. Titre, environnement, étapes de reproduction, résultat attendu, résultat obtenu, gravité, captures d'écran. Copiez-le dans votre outil de suivi, et au bout d'un mois, presque personne ne le remplit.
On y voit d'habitude un problème de discipline. Ce n'en est pas un. C'est un problème de conception : le modèle demande à un humain de recopier des informations qu'une machine a déjà, et les humains refusent, à raison, un travail fastidieux qui ne rapporte rien de visible.
Cet article a donc deux parties. D'abord, un modèle à copier qui mérite d'être gardé. Ensuite, l'argument le plus utile : quels champs supprimer, parce que quelque chose d'autre devrait les remplir.
Le modèle
## Résumé
Une phrase. Ce qui est cassé, du point de vue de l'utilisateur.
## Étapes de reproduction
1.
2.
3.
## Résultat attendu
Ce qui, selon vous, devait se passer.
## Résultat obtenu
Ce qui s'est passé à la place.
## Impact
Qui est touché, à quelle fréquence, et existe-t-il un contournement ?
## Environnement
Navigateur / OS / appareil / version de l'app / URL / type de compte connecté
## Preuves
Capture d'écran, enregistrement, sortie console, requête en échec, ID de requête
C'est tout. Rien de neuf ici : la valeur tient à ce à quoi sert vraiment chaque champ, et c'est là que la plupart des modèles se trompent.
Résumé
Le champ le plus souvent raté. Un bon résumé s'écrit de l'extérieur : « Le bouton Commander ne fait rien à l'étape du paiement avec une carte enregistrée. » Un mauvais s'écrit de l'intérieur d'une hypothèse : « Race condition sur le jeton Stripe. »
Les hypothèses dans le titre font des dégâts, parce qu'elles orientent tous ceux qui lisent le rapport ensuite. Sur les bugs mal titrés, la moitié du temps de tri part à réfuter un diagnostic inventé par l'auteur du rapport et que personne n'a remis en question.
Demandez l'observation. Le diagnostic, c'est le travail de celui qui corrige.
Étapes de reproduction
Le champ dont tout le monde connaît l'importance et que presque tout le monde remplit mal, d'une manière bien précise : on écrit les étapes qu'on croit pertinentes plutôt que celles qu'on a suivies.
On saute « j'avais deux onglets ouverts ». On saute « j'étais sur la page depuis à peu près une heure ». On saute « je suis arrivé par le lien de l'e-mail, pas par le menu ». Ce sont ces omissions qui, d'habitude, sont le bug.
La consigne qui aide : écrivez ce que vous avez fait, depuis l'ouverture de la page, y compris les parties ennuyeuses.
L'état de départ compte autant que les actions. Connecté avec quel compte ? Avec quelles données déjà présentes ? Sur quel forfait ? Une reproduction qui part d'un compte neuf, bien souvent, ne reproduit rien.
Résultat attendu et résultat obtenu
À côté du résumé, ils semblent redondants. Gardez-les quand même.
En les séparant, on fait ressortir toute une catégorie de rapports qui ne sont pas des bugs : les cas où le logiciel se comporte exactement comme prévu et où l'utilisateur attendait autre chose. C'est réel et bon à savoir (un bug de documentation, un bug d'UX ou un bug dans le discours commercial), mais ce n'est pas un défaut de code, et c'est infiniment moins cher à repérer au tri qu'après deux jours d'enquête.
La paire force aussi la précision. « Ça ne marche pas » ne survit pas à la séparation entre attendu et obtenu. L'une des deux cases sera gênante à laisser vague.
Impact
Le champ que la plupart des modèles oublient, et celui qui décide le plus de la suite.
Les listes déroulantes de gravité ne marchent pas. Tout le monde choisit « Haute », parce que depuis sa tâche bloquée, tout paraît urgent. Demandez plutôt les trois choses que la gravité essaie d'approcher :
Qui : moi seul, toute mon équipe, tous les clients sous Safari ?
À quelle fréquence : une fois, à chaque fois, environ une fois sur dix ?
Contournement : y a-t-il un autre moyen de faire le travail ?
« À chaque fois, tous les utilisateurs mobiles, aucun contournement » et « une fois, moi seul, un rafraîchissement règle le problème » se trient tout seuls, sans que personne ne touche à une liste déroulante. Et « une fois sur dix » en dit plus qu'il n'y paraît : intermittent veut dire race condition, cache ou dépendance à la charge, et cela oriente les recherches d'un développeur avant même qu'il ait regardé quoi que ce soit.
Environnement
Indispensable, et la pire utilisation du temps d'un humain de toute cette liste. Gardez cette idée en tête.
Preuves
Les captures d'écran sont la norme, et c'est la forme de preuve la plus faible parmi celles qu'on utilise couramment. Une capture prouve que la page s'affichait mal. Elle ne dit rien du pourquoi.
Classées selon ce qui résout vraiment les bugs :
La requête en échec : méthode, URL, statut, corps de la réponse, et un ID de requête ou de trace si vous en avez un. Un ID de requête transforme un rapport côté client en recherche dans les logs du serveur, le chemin le plus court qui existe entre un rapport et la cause racine.
L'erreur de console avec sa stack : elle pointe vers une ligne de code.
Un enregistrement : il montre le timing et l'enchaînement, ce que les captures ne savent pas faire.
Une capture d'écran : elle montre l'état final.
La plupart des modèles demandent la quatrième et ne mentionnent jamais les trois premières, parce que les trois premières exigent les DevTools et que les personnes qui signalent un bug ne les ont pas ouverts.
Maintenant, supprimez-en la plus grande partie
Reprenez le modèle et triez les champs selon qui peut les fournir.
Seul un humain peut fournir : le résumé, les étapes de reproduction, le résultat attendu, et la partie « qui et à quelle fréquence » de l'impact. Il faut une intention pour les remplir. Aucune instrumentation ne sait ce que quelqu'un essayait de faire ni ce qu'il s'attendait à voir.
Une machine peut fournir, et mieux : l'environnement, le comportement obtenu, et les quatre types de preuves.
Chaque champ du second groupe est un champ où vous demandez à une personne de faire moins bien qu'un script, et où vous le payez en rapports abandonnés.
Regardez ce que « Environnement » demande vraiment. Le navigateur et sa version exacte : la plupart des gens ne savent pas les trouver. La version de l'OS : pareil. La taille du viewport : personne ne la connaît, et c'est le champ qui aurait expliqué le bug de mise en page. L'URL de la page : ils colleront celle de la page où ils se trouvent maintenant, c'est-à-dire votre formulaire de support. La version de l'app ou le hash du build : invisibles pour eux, par conception.
Six données, chacune lisible sans effort depuis le navigateur, chacune coûtant un aller-retour avec le support quand on demande à un humain de la fournir.
Le même argument vaut encore plus pour les preuves. Vous demandez à un utilisateur non technique d'ouvrir les DevTools, de trouver l'onglet réseau, de reproduire le bug, de repérer laquelle des deux cents requêtes est la bonne et de copier sa réponse. C'est une demande qu'il ne satisfera pas. Alors qu'une ligne d'instrumentation suffit.
À quoi devrait ressembler le formulaire
Réduisez-le à ce que seul un humain sait :
## Qu'est-ce qui n'a pas marché ?
[texte libre]
## Qu'est-ce que vous attendiez ?
[texte libre]
## Est-ce déjà arrivé ?
( ) Première fois ( ) Parfois ( ) À chaque fois
Trois champs. Trente secondes. Pendant ce temps, le rapport arrive avec le navigateur, l'OS, le viewport, l'URL, la console avec tout ce qui a été journalisé avant l'ouverture du rapport, le journal réseau avec les statuts et les timings, une relecture de session des dernières minutes, et les clics et saisies de l'utilisateur dans l'ordre.
C'est l'échange sur lequel repose tout l'exercice : l'humain écrit la phrase que lui seul peut écrire, et la machine joint tout le reste.
C'est ce que fait BugDump. Une balise script ajoute un bouton de signalement à la page. L'utilisateur tape ce qui n'a pas marché. Le rapport arrive avec la télémétrie déjà jointe, ainsi qu'une capture d'écran annotée que l'utilisateur peut flouter avant qu'elle quitte son navigateur. L'offre gratuite inclut 500 rapports par projet.
Deux choses à continuer de faire à la main
Automatiser la capture n'automatise pas tout, et mieux vaut être clair sur les limites.
Le tri a toujours besoin d'une personne. Douze rapports sur le même paiement cassé devraient devenir une seule tâche avec douze éléments de preuve, et seul un humain reconnaît qu'il s'agit du même bug. C'est en les regroupant que les rapports en double cessent d'être du bruit et deviennent des données : douze rapports sur cinq navigateurs et deux systèmes d'exploitation forment une matrice, et le motif qu'on y voit désigne en général la cause. BugDump modélise cela directement : les rapports sont des preuves, les tâches sont ce que vous corrigez, et plusieurs rapports se rattachent à une même tâche.
Pour boucler la boucle, il faut toujours une personne. Un rapport envoyé dans le vide apprend à quelqu'un à ne plus rien signaler. Quel que soit votre outil, la personne qui a signalé le bug doit voir que les choses ont bougé. Donnez-lui une page de statut, ou envoyez-lui un message quand le correctif est en ligne. Un portail public où elle voit sa tâche passer de Confirmé à Terminé est la version la moins chère qui fonctionne.
Les modèles ne sont qu'un moyen d'atteindre le vrai objectif : un rapport sur lequel un développeur peut agir sans poser de question. Si un formulaire vous y mène, utilisez celui ci-dessus. Si l'instrumentation vous y mène sans formulaire, c'est strictement mieux : le meilleur modèle de rapport de bug est celui que personne n'a à remplir.
Pour aller plus loin
Comment rédiger un bon rapport de bug (avec checklist) — la structure, le contexte et une checklist pour qu'un rapport soit corrigé plutôt que fermé.
Anatomie d'un rapport de bug – ce que BugDump capture et pourquoi — chaque signal que collecte le widget BugDump, à quoi il sert et lesquels résolvent vraiment des bugs.
De 40 rapports à 6 bugs – comment le tri devrait fonctionner — pourquoi séparer les rapports des tâches évite que la boîte de réception des bugs devienne un cimetière.