Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[run]
source = server
omit =
tests/*

[report]
show_missing = True
skip_covered = False
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
bin
include
lib
lib64
pyvenv.cfg
.Python
tests/
.envrc
__pycache__
__pycache__
.pytest_cache
.coverage
htmlcov/
22 changes: 21 additions & 1 deletion competitions.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,26 @@
"name": "Fall Classic",
"date": "2020-10-22 13:30:00",
"numberOfPlaces": "13"
},
{
"name": "Early Summer Classic",
"date": "2026-06-01 10:00:00",
"numberOfPlaces": "10"
},
{
"name": "Summer Lift Off",
"date": "2026-08-15 09:00:00",
"numberOfPlaces": "20"
},
{
"name": "Winter Games",
"date": "2026-12-05 14:00:00",
"numberOfPlaces": "15"
},
{
"name": "Regional Championship",
"date": "2027-03-20 10:30:00",
"numberOfPlaces": "30"
}
]
}
}
83 changes: 83 additions & 0 deletions locustfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
Tests de performance Locust — GUDLFT Registration Portal.

Critères Phase 2 (rules.md) :
- Liste des compétitions : temps de réponse < 5 secondes
- Mise à jour des points : temps de réponse < 2 secondes
- Nombre d'utilisateurs : 6 (défaut)

Lancer (Flask actif sur le port 5000) :
locust -f locustfile.py --headless -u 6 -r 2 --run-time 30s \\
--host http://127.0.0.1:5000
"""
from locust import HttpUser, between, task
import random

MAX_COMPETITION_LIST_SECONDS = 5
MAX_POINTS_UPDATE_SECONDS = 2

CLUBS = [
{"email": "john@simplylift.co", "name": "Simply Lift"},
{"email": "admin@irontemple.com", "name": "Iron Temple"},
{"email": "kate@shelifts.co.uk", "name": "She Lifts"},
]

UPCOMING_COMPETITION = "Summer Lift Off"


class SecretaryUser(HttpUser):
"""Simule un secrétaire de club connecté à l'application."""

wait_time = between(1, 2)

def on_start(self):
"""Connexion : associe chaque utilisateur virtuel à un club."""
club = random.choice(CLUBS)
self.club_email = club["email"]
self.club_name = club["name"]
self.client.post("/showSummary", data={"email": self.club_email})

@task(3)
def load_competition_list(self):
"""Charge la liste des compétitions à venir (GET /showSummary)."""
with self.client.get(
"/showSummary",
name="/showSummary [liste compétitions]",
catch_response=True,
) as response:
if response.status_code != 200:
response.failure(f"HTTP {response.status_code}")
return
if response.elapsed.total_seconds() > MAX_COMPETITION_LIST_SECONDS:
response.failure(
f"Temps {response.elapsed.total_seconds():.3f}s "
f"> {MAX_COMPETITION_LIST_SECONDS}s"
)

@task(2)
def update_points_via_booking(self):
"""Réserve 1 place et met à jour les points (POST /purchasePlaces)."""
with self.client.post(
"/purchasePlaces",
data={
"club": self.club_name,
"competition": UPCOMING_COMPETITION,
"places": "1",
},
name="/purchasePlaces [mise à jour points]",
catch_response=True,
allow_redirects=False,
) as response:
if response.status_code not in (302, 200):
response.failure(f"HTTP {response.status_code}")
return
if response.elapsed.total_seconds() > MAX_POINTS_UPDATE_SECONDS:
response.failure(
f"Temps {response.elapsed.total_seconds():.3f}s "
f"> {MAX_POINTS_UPDATE_SECONDS}s"
)

@task(1)
def view_public_points_board(self):
"""Consulte le tableau public des points (Phase 2)."""
self.client.get("/clubsPoints", name="/clubsPoints [tableau public]")
5 changes: 5 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[pytest]
testpaths = tests
python_files = test_*.py
python_classes = Test*
python_functions = test_*
156 changes: 156 additions & 0 deletions reports/locust_output.txt

Large diffs are not rendered by default.

79 changes: 79 additions & 0 deletions reports/rapport_performance.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
================================================================
RAPPORT DE PERFORMANCE — GUDLFT Registration Portal
Projet 11 — OpenClassrooms
Date du test : 16/07/2026
================================================================

1. OUTIL ET CONFIGURATION
----------------------------------------------------------------
Outil : Locust 2.44.4
Fichier : locustfile.py
Hôte cible : http://127.0.0.1:5000
Utilisateurs : 6 (conforme au guide de développement)
Taux de montée : 2 utilisateurs/seconde
Durée du test : 30 secondes
Profil simulé : Secrétaire de club connecté (SecretaryUser)

Commande exécutée :
locust -f locustfile.py --headless -u 6 -r 2 --run-time 30s \
--host http://127.0.0.1:5000

2. CRITÈRES DE LA PHASE 2 (rules.md)
----------------------------------------------------------------
| Critère | Seuil max | Résultat |
|--------------------------------------|-----------|----------|
| Chargement liste des compétitions | 5 s | VALIDÉ |
| Mise à jour du total de points | 2 s | VALIDÉ |
| Nombre d'utilisateurs simultanés | 6 | VALIDÉ |

3. RÉSULTATS DÉTAILLÉS
----------------------------------------------------------------

3.1 Liste des compétitions — GET /showSummary
Requêtes totales : 53
Échecs : 0 (0 %)
Temps moyen : 3 ms
Temps médian : 4 ms
Temps maximum : 6 ms
95e percentile : 5 ms
Verdict : VALIDÉ (< 5 s)

3.2 Mise à jour des points — POST /purchasePlaces
Requêtes totales : 47
Échecs : 0 (0 %)
Temps moyen : 3 ms
Temps médian : 4 ms
Temps maximum : 6 ms
95e percentile : 5 ms
Verdict : VALIDÉ (< 2 s)

3.3 Tableau public des points — GET /clubsPoints (Phase 2)
Requêtes totales : 18
Échecs : 0 (0 %)
Temps moyen : 2 ms
Temps médian : 3 ms
Temps maximum : 7 ms
Verdict : VALIDÉ

3.4 Synthèse globale
Requêtes totales : 124
Échecs : 0 (0 %)
Débit moyen : ~4,2 requêtes/seconde

4. SCÉNARIOS TESTÉS
----------------------------------------------------------------
- Connexion par email (POST /showSummary) au démarrage de chaque utilisateur
- Consultation répétée de la liste des compétitions à venir
- Réservation de 1 place (déduction de points en mémoire)
- Consultation du tableau public des points (sans authentification)

5. CONCLUSION
----------------------------------------------------------------
L'application respecte les seuils de performance définis dans les
spécifications fonctionnelles Phase 2. Aucune requête n'a dépassé les
limites de 5 secondes (liste compétitions) ni de 2 secondes (mise à jour
des points), avec 6 utilisateurs simultanés pendant 30 secondes.

Sortie brute Locust : reports/locust_output.txt

================================================================
Loading