- create_dataset.py, compare_snapshots.py, rst_to_dataset.py: Proteus- Testdatensatz anlegen/vergleichen bzw. aus *.rst-Szenarien extrahieren - create_dataset.py: Feld-Alias-Fallback (FIELD_RENAMES) für bekannte Umbenennungen wie stock.move.uom -> unit, bidirektional - merge_dedup_rsts.py: Extrahierte YAMLs pro Version zusammenführen, versionsinterne Duplikate entfernen, abhängigkeitskorrekt sortieren - extract_model_tree.py: Modellbaum (Modelle/Felder) statisch aus dem Tryton-Quellcode ziehen, für 5.0 und 8.0 - model_diff.py, model_coverage.py: 5.0<->8.0-Modelländerungen finden und gegen die aktuelle Testdatenabdeckung abgleichen, priorisiert nach tatsächlicher Änderung - reports/*_merged.yaml: Extraktionsergebnisse für die aktiven Module (rohe *.rst-Quellen bewusst nicht mitversioniert) - Ordner doc ergänzt
4.3 KiB
Modellbaum-Vergleich (5.0 ↔ 8.0)
Werkzeug für die Testdaten-Pipeline: Bevor Testdaten von Hand ergänzt werden, erstmal statisch (kein laufendes Tryton nötig) Schwarz auf Weiß sehen, welche Modelle/Felder es in einer Version überhaupt gibt - damit weder Felder aus 8.0 übernommen werden, die es in 5.0 noch gar nicht gibt (würde beim Anlegen nur Fehler werfen), noch Aufwand in Modelle gesteckt wird, die sich zwischen den Versionen gar nicht verändert haben.
Workflow
1. extract_model_tree.py – Modellbaum aus dem Quellcode ziehen
Scannt den Python-Code ausgewählter Module per AST (kein Import, keine
laufende Instanz) und baut pro Modell (__name__) die Liste aller per
fields.X(...) definierten Felder, mit Typ, Relationsziel
(Many2One/One2Many/Many2Many/One2One/Reference) und - falls literal im
Code erkennbar - required. Modelle werden über PoolMeta-Erweiterungen
hinweg zusammengeführt: Fügt z. B. stock_split eine Klasse mit
__name__ = 'stock.move' hinzu, landen deren Felder unter demselben
Modell-Eintrag, mit Vermerk, aus welchem Modul sie stammen.
Pro Modell wird zusätzlich persisted erkannt (erbt die Klasse ModelSQL
o. ä., oder nur ModelView - dann ist es ein reines Wizard-/
Transient-Formular ohne eigene Tabelle).
python3 extract_model_tree.py --repo /mnt/tryton \
--modules company country currency party product ... \
--output reports/model_tree_5.0.json --report reports/model_tree_5.0.md
Für eine zweite Version denselben Befehl gegen einen zweiten Checkout
laufen lassen (z. B. per git worktree add /tmp/tryton-8.0 8.0, ohne den
Haupt-Checkout umzuschalten).
2. model_diff.py – zwei Modellbäume vergleichen
Sortiert jedes Modell in eine von fünf Kategorien:
- entfernt – Modell gibt es in Version A, nicht mehr in B
- geändert – Feld(er) entfernt oder Typ/Relation/required geändert → echter Kandidat für einen Vergleichslauf
- neu – Modell gibt es erst in B
- nur ergänzt – nur neue Felder dazugekommen, Rest unverändert
- unverändert – komplett identisch geblieben
python3 model_diff.py --tree-a reports/model_tree_5.0.json --label-a 5.0 \
--tree-b reports/model_tree_8.0.json --label-b 8.0 \
--output reports/model_diff.json --report reports/model_diff.md
3. model_coverage.py – gegen die aktuelle Testdaten-Abdeckung abgleichen
Vergleicht einen Modellbaum mit einer gemergten dataset.yaml
(reports/<version>_testdata_merged.yaml, siehe
TESTDATEN.md) und zeigt komplett unabgedeckte Modelle sowie
pro teilweise abgedecktem Modell die ungenutzten Felder (required zuerst).
Drei Kategorien werden aus der Liste unabgedeckter Modelle per Default herausgefiltert (nie von Hand testdatenrelevant, jeweils per Flag wieder einschaltbar):
ir.*/res.*-Kernmodelle (--include-framework)- Wizard-/Transient-Formulare,
persisted: false(--include-transient) - automatisch verwaltete Many2Many-Verknüpfungstabellen, erkennbar am
Bindestrich im Namen wie
party.party-party.category(--include-relations)
Mit --diff reports/model_diff.json wird zusätzlich pro Modell die
Diff-Kategorie aus Schritt 2 eingeblendet und die Liste danach sortiert:
geändert/entfernt zuerst (lohnt sich, dort Testdaten zu ergänzen),
nur ergänzt/unverändert zuletzt (dort ist über den reinen
Codevergleich hinaus erstmal nichts Auffälliges zu erwarten).
python3 model_coverage.py --model-tree reports/model_tree_5.0.json \
--dataset reports/5_testdata_merged.yaml --diff reports/model_diff.json \
--report reports/coverage_5.0.md
Bekannte Grenzen
- Rein statische Analyse: Felder, die nicht als einfaches
name = fields.X(...)auf Klassenebene stehen (z. B. per Schleife/Helper dynamisch erzeugt), werden nicht erkannt. persisted-Erkennung ist eine Textsuche über die Basisklassen-Ausdrücke (ModelSQL/Workflow/DeactivableMixin) - deckt den Normalfall ab, ist aber kein echtes Type-Checking.- Erkennt nur Unterschiede auf Ebene der Feld-Definition im Code
(Typ/Relation/required). Laufzeitverhalten wie Constraints, Defaults oder
DB-Spaltenpräzision kann trotzdem abweichen, ohne hier aufzufallen - dafür
bleibt der eigentliche Testlauf über
create_dataset.py/compare_snapshots.pynötig.