"""Das Gedächtnis der Stilprüfung: was gilt weiter, was wird neu gefragt. Die Prüfung fragt ein Modell. Dieselbe Frage kippt bei Grenzfällen auch bei Temperatur 0 — vorher meldete Runde 1 einen Befund, Runde 2 keinen, Runde 3 wieder einen. Hier steht, unter welchen Bedingungen ein Urteil stehen bleibt. """ import json import pytest import agents import features import ledger import projekte @pytest.fixture def projekt(datenordner): projekte.anlegen("Test") return "Test" def karte(projekt, titel, *funktionen): """funktionen sind (name, regel) oder (name, regel, [testschritte]).""" text = f"\n{titel}\n" for eintrag in funktionen: name, regel, schritte = (*eintrag, [])[:3] text += f"\n{name}\n\n- {regel}\n" if schritte: text += "\n" + "".join(f"- {s}\n" for s in schritte) return features.anlegen(projekt, text) class Zaehler: """Ersetzt das Modell und zählt mit, wie oft überhaupt gefragt wurde.""" def __init__(self, antwort): self.antwort = antwort self.rufe = 0 async def __call__(self, system, nachricht, temperatur=0.0): self.rufe += 1 wert = self.antwort return wert(nachricht, self.rufe) if callable(wert) else wert # ---------------------------------------------------------------- Datei def test_leeres_gedaechtnis_hat_alle_faecher(projekt): stand = ledger.lade(projekt) assert set(stand) == set(ledger.FAECHER) assert all(v == {} for v in stand.values()) def test_kaputte_datei_wird_wie_leer_behandelt(projekt): (projekte.wurzel(projekt) / ledger.DATEI).write_text("{kein json") assert ledger.lade(projekt)["belege"] == {} def test_gemerktes_ueberlebt_den_lauf(projekt): stand = ledger.lade(projekt) stand["belege"][ledger.schluessel("a", "Tun")] = {"abdruck": "x", "datei": "a.py", "beleg": "def tun():"} ledger.sichere(projekt, stand) assert ledger.lade(projekt)["belege"] == stand["belege"] def test_schluessel_bleibt_zerlegbar(projekt): """Titel dürfen alles enthalten — auch das, was als Trennzeichen taugen würde.""" fies = 'Klick auf "x", dann | und \\ und ["a","b"]' assert ledger.teile(ledger.schluessel("karte", fies)) == ["karte", fies] def test_gedaechtnis_ist_kein_feature(projekt): karte(projekt, "Eins") ledger.sichere(projekt, ledger.lade(projekt)) assert [f["sektionen"]["titel"] for f in features.liste(projekt)] == ["Eins"] # ---------------------------------------------------------------- Vision VISION = "\nVision\n\nvision\n\nSo soll es werden\n" def test_vision_ist_eine_eigene_kartenart(projekt): f = features.anlegen(projekt, VISION) assert f["sektionen"]["art"] == "vision" assert f["sektionen"]["ziel"] == "So soll es werden" def test_unbekannte_art_bleibt_kern(projekt): f = features.anlegen(projekt, "\nX\n\nwichtig\n") assert f["sektionen"]["art"] == "kern" def test_keine_pruefung_fasst_die_vision_an(projekt): """Die Vision ist die Vorlage, nicht der Prüfling.""" karte(projekt, "Eins", ("Etwas starten", "Knopf")) features.anlegen(projekt, VISION) assert len(features.liste(projekt)) == 2 titel = [f["sektionen"]["titel"] for f in features.pruefbar(projekt)] assert titel == ["Eins"] # ---------------------------------------------------------------- Prüfung 1 async def test_stilurteil_wird_gemerkt_und_nicht_neu_gefragt(projekt, monkeypatch): """176 Anfragen je Lauf brachten den Anbieter zum Drosseln. Unveränderter Ausschnitt bei unverändertem Katalog heißt: das Urteil von vorhin gilt.""" import pruefung karte(projekt, "Eins", ("Etwas starten", "Knopf")) modell = Zaehler('{"felder": {}}') monkeypatch.setattr(agents, "frage", modell) liste, arbeite, abschluss = await pruefung._stil_aufgaben(projekt) for a in liste: assert await arbeite(a, None) == [] abschluss() erste = modell.rufe assert erste >= len(pruefung.TEMPERATUREN) liste, arbeite, abschluss = await pruefung._stil_aufgaben(projekt) for a in liste: assert await arbeite(a, None) == [] assert modell.rufe == erste # keine einzige neue Anfrage async def test_geaenderter_text_wird_neu_gefragt(projekt, monkeypatch): import pruefung karte(projekt, "Eins", ("Etwas starten", "Knopf")) modell = Zaehler('{"felder": {}}') monkeypatch.setattr(agents, "frage", modell) liste, arbeite, abschluss = await pruefung._stil_aufgaben(projekt) for a in liste: await arbeite(a, None) abschluss() vorher = modell.rufe datei = projekte.wurzel(projekt) / f"{features.liste(projekt)[0]['id']}.md" datei.write_text(datei.read_text().replace("- Knopf", "- Ganz anderer Text")) liste, arbeite, _ = await pruefung._stil_aufgaben(projekt) for a in liste: await arbeite(a, None) assert modell.rufe > vorher async def test_gemessener_verstoss_kommt_nie_aus_dem_gedaechtnis(projekt, monkeypatch): """Sonst bliebe eine neu hinzugekommene Messregel an alten Karten wirkungslos.""" import pruefung karte(projekt, "Eins", ("Etwas starten", "Auch Passwort prüfen.")) modell = Zaehler('{"felder": {"regeln": {"neu": "- Passwort prüfen",' ' "grund": "Füllwort", "regel": "x"}}}') monkeypatch.setattr(agents, "frage", modell) for lauf in range(2): liste, arbeite, abschluss = await pruefung._stil_aufgaben(projekt) gefunden = [p for a in liste for p in await arbeite(a, None)] abschluss() assert [p["vorschlag"] for p in gefunden] == ["Passwort prüfen"], lauf assert modell.rufe > len(pruefung.TEMPERATUREN) # zweimal wirklich gefragt