EXEMPLE : une entreprise fictive. Pas un client d'Adwaizer.
Version française de l'exemple de rapport en anglais. Même contenu et mêmes chiffres que la version anglaise ; en cas d'écart, la version anglaise fait foi. Les noms de fichiers, les commandes, le code et les sorties de tests restent en anglais.
Correctif logiciel : portée écrite, test qui échoue, résumé du correctif et remise pour Ferngate Cycle Hire (exemple)
Préparé par : Adwaizer AI Consulting Inc. · Mandat : correction de bogue ou petite fonctionnalité, niveau Starter (un correctif dans un dépôt, 5 jours ouvrables) · Version du rapport : exemple, octobre 2026
Ce qu'est cette page. Voici tout ce que le client reçoit dans une commande de correctif logiciel : la portée écrite au jour 1, le test qui échoue au jour 2, le résumé du correctif aux jours 3-4, puis la note de remise, la liste de vérification d'acceptation et le texte du jalon Upwork au jour 5. Ferngate Cycle Hire, son dépôt
ferngate/booking-apiet chaque fichier, test, commit, pull request et chiffre ci-dessous sont inventés pour montrer la forme et le niveau de détail ; rien de tout cela n'existe. Dans une vraie commande, chaque ligne renvoie au dépôt du client, à sa pull request et à son exécution des tests.
Comment lire les preuves. Une « preuve » est ce que le client peut ouvrir et vérifier : un fichier et une ligne dans son dépôt, le nom d'un test, une commande et sa sortie. Rien ici n'a été exécuté sur une vraie application.
1. Portée écrite (jour 1, convenue par écrit avant tout développement)
Ferngate Cycle Hire est une boutique fictive de location de vélos. Son API de réservation est une application FastAPI en Python 3.12 avec une base de données PostgreSQL et une suite de tests pytest. Le propriétaire a signalé un bogue dans la messagerie d'Upwork, avec deux captures d'écran de la page de réservation.
Exécution avant toute modification. Nous avons cloné le dépôt à main @ 4be1c07 (fictif), suivi le README (pip install -r requirements-dev.txt, pytest) et noté le résultat du jour : 96 passed, 0 failed, 2 skipped (les deux tests ignorés ont besoin d'un environnement de paiement de test en direct et sont aussi ignorés dans l'intégration continue du client).
| Élément | Convenu |
|---|---|
| Le bogue | Un vélo rendu à une heure donnée ne peut pas être réservé par le client suivant à partir de cette même heure. Exemple du client : le vélo #14 est réservé de 10:00 à 13:00, puis une demande de 13:00 à 16:00 le même jour est refusée avec « This bike is not available for the times you chose. » |
| Comportement attendu (selon le client) | « Si un vélo revient à 1 h, quelqu'un d'autre devrait pouvoir le prendre à 1 h. Les réservations dos à dos, c'est comme ça qu'on remplit la fin de semaine. » |
| Ce qu'on observe | HTTP 409 de POST /bookings avec {"detail": "bike_unavailable"} pour toute réservation qui commence exactement quand une autre se termine, ou se termine exactement quand une autre commence |
| Fichiers probablement touchés | app/bookings/availability.py (la vérification de chevauchement) ; un nouveau test dans tests/bookings/test_availability.py |
| Hors portée | Le délai de nettoyage entre les réservations (le client en a parlé ; c'est une nouvelle fonctionnalité, soumise à part s'il la veut) ; l'interface de la page de réservation ; le parcours de paiement ; toute migration de base de données ; les deux tests de paiement ignorés |
| Vérifications d'acceptation | Les quatre vérifications de la section 4.2 |
Registre des risques et des problèmes (jour 1).
| # | Risque ou problème | Responsable | Statut |
|---|---|---|---|
| R1 | Les réservations sont enregistrées en heure locale, sans fuseau horaire ; un correctif qui compare les heures autrement pourrait décaler des réservations au changement d'heure | Adwaizer | Fermé au jour 3 : le correctif garde le même type de comparaison et les tests existants sur le changement d'heure passent toujours |
| R2 | Le fichier .env.example du dépôt contient seulement une clé de paiement fictive ; aucune vraie clé n'a été trouvée dans le dépôt ni dans son historique | Adwaizer | Fermé : rien à remplacer |
| I1 | L'intégration continue du client ne s'exécute que sur les poussées vers main, donc une pull request n'affiche aucune exécution | Client | Ouvert : l'exécution des tests est montrée dans la description de la pull request (section 3.3) |
La portée ci-dessus a été envoyée dans la messagerie d'Upwork au jour 1 et le client a répondu « Oui, allez-y » le jour même. Aucun développement n'a commencé avant cette réponse.
2. Le test qui échoue (jour 2)
Le bogue se reproduit sur le code actuel du client, dans son propre cadre de test (pytest). Le test réserve le vélo #14 de 10:00 à 13:00, puis demande le même vélo de 13:00 à 16:00. Il vérifie aussi le cas que le client n'a pas mentionné mais que la même ligne cause : une réservation qui se termine exactement quand une réservation existante commence.
# tests/bookings/test_availability.py
from datetime import datetime
import pytest
from app.bookings.availability import is_available
from tests.factories import make_booking
@pytest.mark.parametrize(
"start, end",
[
("2026-10-24T13:00", "2026-10-24T16:00"), # starts when the earlier booking ends
("2026-10-24T07:00", "2026-10-24T10:00"), # ends when the earlier booking starts
],
)
def test_back_to_back_booking_is_available(db, start, end):
make_booking(db, bike_id=14, start="2026-10-24T10:00", end="2026-10-24T13:00")
assert is_available(
db,
bike_id=14,
start=datetime.fromisoformat(start),
end=datetime.fromisoformat(end),
)
def test_overlapping_booking_is_still_refused(db):
make_booking(db, bike_id=14, start="2026-10-24T10:00", end="2026-10-24T13:00")
assert not is_available(
db,
bike_id=14,
start=datetime.fromisoformat("2026-10-24T12:59"),
end=datetime.fromisoformat("2026-10-24T16:00"),
)
Résultat sur le code actuel du client (pytest tests/bookings/test_availability.py) :
FAILED tests/bookings/test_availability.py::test_back_to_back_booking_is_available[2026-10-24T13:00-2026-10-24T16:00] - assert False
FAILED tests/bookings/test_availability.py::test_back_to_back_booking_is_available[2026-10-24T07:00-2026-10-24T10:00] - assert False
PASSED tests/bookings/test_availability.py::test_overlapping_booking_is_still_refused
2 failed, 1 passed
Les deux cas dos à dos échouent : c'est le bogue du client. Le cas de chevauchement passe aujourd'hui et doit continuer de passer après le correctif, pour qu'une vraie double réservation soit toujours refusée.
Cause première. app/bookings/availability.py, ligne 31 (fictive), considère que deux réservations se chevauchent quand existing.start <= requested.end and requested.start <= existing.end. Avec <=, une réservation qui se termine à 13:00 et une autre qui commence à 13:00 sont comptées comme un chevauchement. Les heures de réservation sont semi-ouvertes (un vélo rendu à 13:00 est libre à 13:00), donc la comparaison doit utiliser <.
Gabriel a lu le test qui échoue au jour 2 et a confirmé avec le client qu'il montre bien son bogue.
3. Résumé du correctif (jours 3-4)
3.1 Le changement en mots
Une comparaison a changé dans une fonction : dans is_available, deux réservations ne se chevauchent maintenant que quand existing.start < requested.end and requested.start < existing.end. Rien d'autre n'a changé dans la logique de réservation. La requête SQL qui charge les réservations candidates utilisait le même filtre <= ; elle a donc été changée en < de la même façon. Sans cela, la requête renverrait toujours la réservation dos à dos et la fonction la refuserait.
| Fichier | Changement |
|---|---|
app/bookings/availability.py | Le test de chevauchement et la requête des candidates utilisent < au lieu de <= (2 lignes), plus un commentaire d'une ligne indiquant que les heures de réservation sont semi-ouvertes |
tests/bookings/test_availability.py (nouveau) | Les trois tests de la section 2 |
Pull request : ferngate/booking-api#41 (fictive), à partir de la branche fix/back-to-back-bookings. Diff : +46 / -2 lignes dans 2 fichiers. Aucune dépendance, migration, aucun paramètre ni variable d'environnement n'a changé.
3.2 Envisagé et laissé de côté
- Un délai de nettoyage entre les réservations. Le client a mentionné vouloir 15 minutes entre deux locations. Cela change la règle au lieu de la corriger ; c'est donc hors portée et inscrit dans la note de remise comme commande suivante possible.
- Les fuseaux horaires. Les réservations sont enregistrées sans fuseau horaire (R1). Le correctif ne change pas cela ; le changer toucherait chaque ligne de réservation.
3.3 Vérifications exécutées sur le changement
| Vérification | Résultat |
|---|---|
| Nouveaux tests sur l'ancien code | 2 failed, 1 passed (section 2) |
| Nouveaux tests avec le changement | 3 passed |
Suite complète (pytest) | 99 passed, 0 failed, 2 skipped (96 existants + 3 nouveaux ; les mêmes 2 tests de paiement ignorés qu'au jour 1) |
Lint et vérification des types des fichiers modifiés (ruff check, mypy app/bookings/availability.py) | 0 erreur |
| Session de révision distincte, par rapport à la portée écrite | Approuvé ; seuls les deux fichiers prévus ont changé ; a demandé le commentaire sur les heures semi-ouvertes, qui a été ajouté |
Recherche de secrets dans les commits (gitleaks) | Aucune fuite trouvée |
| Lecture par Gabriel de la pull request révisée | Approuvée pour la remise |
4. Note de remise et liste de vérification d'acceptation (jour 5)
4.1 Note de remise
Ce qui a changé et pourquoi. Un vélo rendu à une heure donnée peut maintenant être réservé à partir de cette même heure. La vérification de disponibilité considérait qu'une réservation se terminant à 13:00 et une autre commençant à 13:00 étaient en conflit ; elle traite maintenant les heures de réservation comme « à partir du début, jusqu'à la fin exclue », ce qui correspond déjà à la façon de faire au comptoir. Un vrai chevauchement (même d'une minute) est toujours refusé.
Comment exécuter le nouveau test.
pip install -r requirements-dev.txt
pytest tests/bookings/test_availability.py
Résultat attendu : 3 passed. Pour voir le bogue sur votre ancien code, revenez à main avant la pull request, gardez le nouveau fichier de test et lancez la même commande : les deux cas dos à dos échouent.
Quoi vérifier dans l'application après la fusion. Sur votre site de préproduction, réservez n'importe quel vélo de 10:00 à 13:00, puis réservez le même vélo de 13:00 à 16:00. La deuxième réservation est acceptée. Essayez ensuite de 12:30 à 16:00 : elle est refusée.
Constaté et laissé de côté.
| Élément | Pourquoi c'est important | Prochaine étape suggérée |
|---|---|---|
| Délai de nettoyage entre les réservations | Vous en avez parlé ; c'est une nouvelle r ègle, pas ce correctif | Une commande distincte de petite fonctionnalité si vous la voulez |
| Heures de réservation enregistrées sans fuseau horaire | Un risque au changement d'heure si vous ouvrez un jour un deuxième point de service dans un autre fuseau | Rien à faire aujourd'hui ; à examiner avant tout projet à plusieurs points de service |
L'intégration continue ne s'exécute que sur main | Une pull request n'affiche aucune exécution des tests avant d'être fusionnée | Ajouter pull_request au déclencheur de votre fichier d'intégration continue (un changement d'une ligne que vous pouvez faire) |
4.2 Liste de vérification d'acceptation (pour le client)
- Le nouveau test échoue sur votre ancien code et passe avec le changement (
pytest tests/bookings/test_availability.py). - Votre suite de tests existante passe toujours (
pytest: 99 passed, 2 skipped, comme le montre la pull request). - En préproduction, une réservation dos à dos du même vélo est acceptée et une réservation qui chevauche est refusée, comme le décrit la note de remise.
- Aucun fichier n'a changé en dehors de
app/bookings/availability.py, sauf le nouveau fichier de test.
Une vérification qui échoue est corrigée dans un délai de 5 jours ouvrables, sans frais. C'est vous qui fusionnez la pull request et qui déployez ; nous ne fusionnons jamais dans votre branche principale et nous ne déployons jamais.
5. Texte de remise du jalon Upwork
Bonjour, le correctif pour les réservations dos à dos est prêt pour votre examen.
- Pull request : ferngate/booking-api#41 (2 fichiers : la vérification de disponibilité et un nouveau fichier de test).
- Ce qui a changé : un vélo rendu à une heure donnée peut maintenant être réservé à partir de cette même heure ; les réservations qui se chevauchent sont toujours refusées.
- Preuve : le nouveau test échoue sur votre code actuel et passe avec le correctif. Votre suite complète passe (99 passed, 2 skipped, les mêmes 2 tests ignorés qu'avant).
- La note de remise dans la pull request explique comment exécuter le test, quoi vérifier en préproduction, et trois choses que nous avons remarquées et laissées de côté (le délai de nettoyage dont vous avez parlé en fait partie).
Veuillez passer en revue la liste de vérification d'acceptation de 4 points dans la pull request. Si quelque chose ne se vérifie pas, dites-le-moi ici et nous le corrigeons dans un délai de 5 jours ouvrables, sans frais. Une fois satisfait, veuillez approuver ce jalon et fusionner vous-même la pull request ; nous ne fusionnons pas et ne déployons pas.
Merci.