Skip to content

Commit 75da8ed

Browse files
Test: Ajout des tests unitaires pour ParseurLogApache (#16)
- Ajout des tests unitaires pour la classe ParseurLogApache afin de vérifier que la classe parvient à faire une analyse syntaxique correcte d'un fichier de log Apache
1 parent d54e9f7 commit 75da8ed

1 file changed

Lines changed: 175 additions & 0 deletions

File tree

tests/test_parseur_log_apache.py

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
"""
2+
Module des tests unitaires pour le parseur de fichier de log Apache.
3+
"""
4+
5+
import pytest
6+
from re import match
7+
from datetime import datetime, timezone, timedelta
8+
from parse.parseur_log_apache import ParseurLogApache, FormatLogApacheInvalideException
9+
10+
# Données utilisées pour les tests unitaires
11+
12+
# Liste d'entrées valides
13+
lignes_log_apache = [
14+
# Première entrée
15+
'192.168.1.1 - - [12/Jan/2025:10:15:32 +0000] "GET /index.html HTTP/1.1" 200 532',
16+
# Deuxième entrée
17+
'::1 - - [05/Mar/2025:16:59:43 +0100] "POST /backend/getConnexion.php HTTP/1.1" 200 20'
18+
'"http://localhost/backend/connexion.php?titre=Connexion" "Mozilla/5.0 (Windows NT 10.0;'
19+
' Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36"',
20+
# Troisième entrée
21+
'::1 - - [05/Mar/2025:16:59:43 +0100] "DELETE / HTTP/2.1" 200 20'
22+
]
23+
24+
# Liste d'entrées invalides
25+
lignes_log_apache_invalides = [
26+
'',
27+
'Une ligne avec un format invalide !',
28+
'::1 - - [05/Mar/2025:16:59:43] "DELETE / HTTP/2.1" 200 20',
29+
'192.168.1.1 - [12/Jan/2025:10:15:32 +0000] "GET /index.html HTTP/1.1" test 532'
30+
]
31+
32+
@pytest.fixture()
33+
def log_apache(tmp_path):
34+
"""
35+
Fixture pour créer et récupérer un fichier de log Apache temporaire.
36+
Cette fixture permet de générer un fichier de log Apache temporaire contenant
37+
soit des lignes valides, soit des lignes invalides selon le paramètre fourni.
38+
Args:
39+
tmp_path (Path): Chemin temporaire fourni par pytest.
40+
Returns:
41+
Callable[[bool], Path]: Une fonction qui crée et retourne le chemin
42+
du fichier de log temporaire.
43+
"""
44+
def _creer_log(valide):
45+
"""
46+
Crée un fichier de log Apache temporaire.
47+
Args:
48+
valide (bool): Si True, le fichier contient des lignes de log valides.
49+
Sinon, il contient des lignes invalides.
50+
Returns:
51+
Path: Le chemin du fichier de log temporaire créé.
52+
"""
53+
contenu = (
54+
"\n".join(lignes_log_apache)
55+
if valide == True
56+
else "\n".join(lignes_log_apache_invalides)
57+
)
58+
fichier_temp = tmp_path / "access.log"
59+
fichier_temp.write_text(contenu)
60+
return fichier_temp
61+
return _creer_log
62+
63+
@pytest.fixture
64+
def parseur_log_apache(log_apache, request):
65+
"""
66+
Fixture pour initialiser le parseur de log Apache.
67+
Retourne une instance de la classe ParseurLogApache pour être utilisée dans les tests.
68+
Returns:
69+
ParseurLogApache: Une instance de la classe ParseurArgumentsCLI.
70+
"""
71+
if hasattr(request, "param") and request.param == False:
72+
return ParseurLogApache(log_apache(False))
73+
return ParseurLogApache(log_apache(True))
74+
75+
76+
# Tests unitaires
77+
78+
def test_exception_fichier_invalide():
79+
"""
80+
Vérifie qu'une exception est bien levée lorsque le fichier n'existe pas.
81+
Returns:
82+
None
83+
"""
84+
with pytest.raises(FileNotFoundError):
85+
parseur = ParseurLogApache("fichier/existe/pas.txt")
86+
87+
@pytest.mark.parametrize("parseur_log_apache", [False], indirect=["parseur_log_apache"])
88+
def test_exception_fichier_invalide(parseur_log_apache):
89+
"""
90+
Vérifie qu'une exception est bien levée lorsque le format d'un fichier n'est
91+
pas valide (une entrée invalide).
92+
Args:
93+
parseur_arguments_cli (ParseurArgumentsCLI): Fixture pour l'instance
94+
de la classe ParseurLogApache.
95+
Returns:
96+
None
97+
"""
98+
with pytest.raises(FormatLogApacheInvalideException):
99+
fichier = parseur_log_apache.parse_fichier()
100+
101+
@pytest.mark.parametrize("ligne_log", lignes_log_apache_invalides)
102+
def test_exception_entree_invalide(parseur_log_apache, ligne_log):
103+
"""
104+
Vérifie qu'une exception est bien levée lorsque le format d'au moins une
105+
entrée est invalide dans un fichier de log Apache.
106+
Args:
107+
parseur_arguments_cli (ParseurArgumentsCLI): Fixture pour l'instance
108+
de la classe ParseurLogApache.
109+
ligne_log (str): L'entrée à analyser.
110+
Returns:
111+
None
112+
"""
113+
with pytest.raises(FormatLogApacheInvalideException):
114+
parseur_log_apache.parse_entree(ligne_log)
115+
116+
def test_nombre_entrees_valide(parseur_log_apache):
117+
"""
118+
Vérifie que le nombre d'entrées trouvé correspond au nombre de ligne dans le log.
119+
Args:
120+
parseur_arguments_cli (ParseurArgumentsCLI): Fixture pour l'instance
121+
de la classe ParseurLogApache.
122+
Returns:
123+
None
124+
"""
125+
fichier_log = parseur_log_apache.parse_fichier()
126+
assert len(fichier_log.entrees) == len(lignes_log_apache)
127+
128+
@pytest.mark.parametrize("nom_information, retour_attendu", [
129+
("ip", "192.168.1.1"),
130+
("rfc", None),
131+
("horodatage", "12/Jan/2025:10:15:32 +0000"),
132+
("Existe pas !", None)
133+
])
134+
def test_regex_recuperation_information_entree(parseur_log_apache, nom_information, retour_attendu):
135+
"""
136+
Vérifie que la récupération des informations à partir d'un résultat de regex fonctionne
137+
correctement et que toutes valeurs introuvables ou égales à - renvoient None.
138+
Args:
139+
parseur_arguments_cli (ParseurArgumentsCLI): Fixture pour l'instance
140+
de la classe ParseurLogApache.
141+
nom_information (str): Nom de l'information à récupérer.
142+
retour_attendu (Union[None, str]): La valeur attendue de l'information.
143+
Returns:
144+
None
145+
"""
146+
ligne = '192.168.1.1 - - [12/Jan/2025:10:15:32 +0000] "GET /index.html HTTP/1.1" 200 532'
147+
analyse = match(parseur_log_apache.PATTERN_ENTREE_LOG_APACHE, ligne)
148+
resultat_analyse = analyse.groupdict()
149+
assert parseur_log_apache.get_information_entree(resultat_analyse, nom_information) == retour_attendu
150+
151+
def test_parsage_entree_valide(parseur_log_apache):
152+
"""
153+
Vérifie qu'une entrée est correctement analysée et que les informations partent
154+
au bon endroit avec le bon typage.
155+
Args:
156+
parseur_arguments_cli (ParseurArgumentsCLI): Fixture pour l'instance
157+
de la classe ParseurLogApache.
158+
Returns:
159+
None
160+
"""
161+
ligne = '192.168.1.1 - - [12/Jan/2025:10:15:32 +0000] "GET /index.html HTTP/1.1" ' \
162+
'200 532 "/home" "Chrome/133.0.0.0"'
163+
entree = parseur_log_apache.parse_entree(ligne)
164+
assert entree.client.adresse_ip == "192.168.1.1"
165+
assert entree.client.identifiant_rfc == None
166+
assert entree.client.nom_utilisateur == None
167+
assert entree.client.agent_utilisateur == "Chrome/133.0.0.0"
168+
assert entree.requete.horodatage == datetime(2025, 1, 12, 10, 15, 32,
169+
tzinfo=timezone(timedelta(hours=0)))
170+
assert entree.requete.methode_http == "GET"
171+
assert entree.requete.url == "/index.html"
172+
assert entree.requete.protocole_http == "HTTP/1.1"
173+
assert entree.requete.ancienne_url == "/home"
174+
assert entree.reponse.code_status_http == 200
175+
assert entree.reponse.taille_octets == 532

0 commit comments

Comments
 (0)