♻️refactor(parser): refactor parsing methods

This commit is contained in:
2026-09-10 09:46:16 +02:00
parent d37733457f
commit cf83a06cfe
3 changed files with 91 additions and 84 deletions
+44 -38
View File
@@ -3,48 +3,50 @@ from pathlib import Path
import pytest
from logwatcher.models import LogEntry
from logwatcher.parser import parse_log_file, parse_log_line
from logwatcher.parser import parse_file, parse_line
@pytest.fixture(name="empty_log_file")
def empty_log_file_fixture(invalid_log_dir: Path) -> Path:
"""
Path of an empty log file.
Ensures the parser does not raise an exception
and returns an empty list.
Path of an empty log file.
Ensures the parser does not raise an exception
and returns an empty list.
"""
return invalid_log_dir / "empty_file.txt"
@pytest.fixture(name="bad_log_file")
def bad_log_file_fixture(invalid_log_dir: Path) -> Path:
"""
Path of a file containing only incorrectly formatted lines.
Each line fails at a different point in LOG_PATTERN
(invalid IP, missing timestamp, missing DOSSIER EN COURS, etc.).
No LogEntry should be produced.
Path of a file containing only incorrectly formatted lines.
Each line fails at a different point in LOG_PATTERN
(invalid IP, missing timestamp, missing DOSSIER EN COURS, etc.).
No LogEntry should be produced.
"""
return invalid_log_dir / "bad_log_file.txt"
@pytest.fixture(name="specific_logs")
def specific_logs_fixture(valid_log_dir: Path) -> list[str]:
"""
Single log lines chosen to cover specific cases.
Each line is structurally valid and must be parsed
successfully. Used for unit tests of parse_log_line().
Single log lines chosen to cover specific cases.
Each line is structurally valid and must be parsed
successfully. Used for unit tests of parse_line().
"""
log_file = valid_log_dir / "specific_logs.txt"
with open(log_file, 'r') as file:
with open(log_file, "r") as file:
return file.readlines()
def test_parse_log_line(specific_logs: list[str]):
def test_parse_line(specific_logs: list[str]):
"""
Every structurally valid line produces a complete LogEntry.
Ensures no required field is empty or None after parsing
a line conforming to the LAME MDC format.
Every structurally valid line produces a complete LogEntry.
Ensures no required field is empty or None after parsing
a line conforming to the LAME MDC format.
"""
for log_line in specific_logs:
log_entry = parse_log_line(log_line)
log_entry = parse_line(log_line)
assert log_entry is not None
assert log_entry.server_ip is not None
assert log_entry.mdc_server_name is not None
@@ -52,49 +54,53 @@ def test_parse_log_line(specific_logs: list[str]):
assert log_entry.store_name is not None
assert log_entry.error_time is not None
assert log_entry.error_message is not None
assert log_entry.raw_line != ''
assert log_entry.raw_line != ""
def test_parse_empty_log_line():
"""
An empty or structurally invalid line returns None.
Covered cases:
- Empty string.
- Directory header (\"Répertoire scanné : \\\\...\").
An empty or structurally invalid line returns None.
Covered cases:
- Empty string.
- Directory header (\"Répertoire scanné : \\\\...\").
"""
log_entry = parse_log_line("")
log_entry = parse_line("")
assert not log_entry
log_entry = parse_log_line("Répertoire scanné : \\\\192.168.60.48\\e$\\MDC_9110\\Logs")
log_entry = parse_line("Répertoire scanné : \\\\192.168.60.48\\e$\\MDC_9110\\Logs")
assert not log_entry
def test_parse_valid_log_file(original_log_dir: Path):
"""
Each real log file produces at least one valid LogEntry.
Integration test: files provided by technicians contain
a mix of valid lines and lines to be ignored.
Ensures the parser extracts at least one entry per file.
Each real log file produces at least one valid LogEntry.
Integration test: files provided by technicians contain
a mix of valid lines and lines to be ignored.
Ensures the parser extracts at least one entry per file.
"""
for log_file in original_log_dir.glob("CR_*"):
log_list = parse_log_file(log_file)
log_list = parse_file(log_file)
assert len(log_list) > 0
for log_entry in log_list:
assert isinstance(log_entry, LogEntry)
def test_parse_empty_log_file(empty_log_file):
"""
An empty log file can be parsed and must returns an
empty LogEntry list.
An empty log file can be parsed and must returns an
empty LogEntry list.
"""
log_list = parse_log_file(empty_log_file)
log_list = parse_file(empty_log_file)
assert len(log_list) == 0
def test_parse_bad_log_file(bad_log_file):
"""
A file containing only invalid lines produces nothing.
Any line that does not match the LAME MDC structure
(IP, timestamps, DOSSIER EN COURS, error message)
must be silently ignored.
A file containing only invalid lines produces nothing.
Any line that does not match the LAME MDC structure
(IP, timestamps, DOSSIER EN COURS, error message)
must be silently ignored.
"""
log_list = parse_log_file(bad_log_file)
assert len(log_list) == 0
log_list = parse_file(bad_log_file)
assert len(log_list) == 0