Files
tryton-db-migration/doc/MODELLVERGLEICH.md
T
uha4 c0dd24b6c5 Proteus-Zweig: dataset.yaml-Pipeline und 5.0/8.0-Modellbaumvergleich
- 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
2026-08-22 10:52:13 +02:00

4.3 KiB
Raw Blame History

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.py nötig.