2025-08-05 14:38:54 +04:00

75 lines
2.7 KiB
Python

import sys
import pathlib
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent))
import os
import xml.etree.ElementTree as ET
import pytest
from enhanced_mcm_generator import EnhancedMCMGenerator
def _canonicalize_xml(path: str) -> bytes:
"""Return a canonicalised representation of an L5X / XML file.
The function removes volatile attributes (e.g. ExportDate) and sorts
attributes of every element so the resulting byte string is stable
across Python runs and operating systems.
"""
tree = ET.parse(path)
root = tree.getroot()
# Remove volatile attributes that change on every export (present on many elements)
for elem in root.iter():
elem.attrib.pop("ExportDate", None)
# Recursively sort attributes to obtain a deterministic ordering
def _sort_attrs(elem: ET.Element):
if elem.attrib:
# Convert to list with sorted items to keep ElementTree stable
sorted_items = sorted(elem.attrib.items())
elem.attrib.clear()
elem.attrib.update(sorted_items)
for child in elem:
_sort_attrs(child)
_sort_attrs(root)
# Normalise text nodes: strip leading/trailing whitespace so that
# cosmetic indentation inside <Comment> elements does not cause false
# differences.
for elem in root.iter():
if elem.text is not None:
elem.text = elem.text.strip()
# ElementTree does not guarantee attribute ordering when converting to
# string, but because we have manually re-inserted sorted attributes we
# get a deterministic output here.
return ET.tostring(root, encoding="utf-8")
@pytest.mark.regression
def test_generated_project_matches_golden(tmp_path):
"""Generate the project and compare it against the golden reference.
If this test fails, a refactor has changed the *semantic* XML output.
Check the diff to decide whether the change is intended or not.
"""
project_name = "MCM04_Chute_Load"
# 1. Run the generator to build a fresh project under the temporary dir
generator = EnhancedMCMGenerator(project_name, excel_file="Data.xlsx")
assert generator.load_and_process_data(), "Failed to load/process Excel data"
output_path = generator.generate_complete_project()
# 2. Compare with the golden file
golden_path = os.path.join(
"generated_projects", "MCM04_Chute_Load_To_Compare_Against.L5X"
)
assert os.path.exists(golden_path), "Golden file is missing"
assert _canonicalize_xml(output_path) == _canonicalize_xml(
golden_path
), "Generated project differs from golden reference"