2026-09-17 11:42:58 +02:00
|
|
|
|
"""Profil beigelegter Datendateien – deterministisch, ohne LLM."""
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
|
refactor: Pipeline-Stufen in Ordner mit ihren Prompts
Im Wurzelverzeichnis liegt nur noch TextToModel.py (Ablauf und CLI).
Jede Stufe liegt mit Code und Prompt in einem eigenen Ordner: core,
understanding, modeling, checks, solving, reporting, data, benchmark;
Tests unter tests/, Aufgaben unter tasks/. understand_task,
text_to_model/revise_model und review_assumptions/needs_work/select_best
sind aus TextToModel.py zu ihren Prompts gewandert, inhaltlich
unveraendert. Prompt-Kennung des Benchmarks bleibt 93744636095a.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 12:11:51 +02:00
|
|
|
|
from data.data_profile import profile_file, profile_files, to_prompt
|
2026-09-17 11:42:58 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture
|
|
|
|
|
|
def kurse(tmp_path):
|
|
|
|
|
|
datei = tmp_path / "kurse.csv"
|
|
|
|
|
|
datei.write_text("Aktie;Rendite;Risiko;Gebuehr\nA01;6,9;2,04;0,68\nA02;14,4;1,63;0,74\nA03;11,5;;0,39\n",
|
|
|
|
|
|
encoding="utf-8")
|
|
|
|
|
|
return datei
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_german_numbers_are_recognised(kurse):
|
|
|
|
|
|
# deutsche Daten sind der Normalfall: "6,9" ist eine Zahl, keine Zeichenkette
|
|
|
|
|
|
profil = profile_file(kurse)
|
|
|
|
|
|
assert profil.rows == 3 and len(profil.columns) == 4
|
|
|
|
|
|
rendite = next(s for s in profil.columns if s.name == "Rendite")
|
|
|
|
|
|
assert rendite.dtype == "Zahl"
|
|
|
|
|
|
assert rendite.minimum == pytest.approx(6.9) and rendite.maximum == pytest.approx(14.4)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_text_columns_and_gaps(kurse):
|
|
|
|
|
|
profil = profile_file(kurse)
|
|
|
|
|
|
assert next(s for s in profil.columns if s.name == "Aktie").dtype == "Text"
|
|
|
|
|
|
assert next(s for s in profil.columns if s.name == "Risiko").missing == 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_separator_is_detected(tmp_path):
|
|
|
|
|
|
komma = tmp_path / "en.csv"
|
|
|
|
|
|
komma.write_text("name,value\nfoo,1.5\nbar,2.5\n")
|
|
|
|
|
|
profil = profile_file(komma)
|
|
|
|
|
|
assert [s.name for s in profil.columns] == ["name", "value"]
|
|
|
|
|
|
assert next(s for s in profil.columns if s.name == "value").mean == pytest.approx(2.0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_unreadable_file_is_reported_not_raised(tmp_path):
|
|
|
|
|
|
profil = profile_file(tmp_path / "gibtsnicht.csv")
|
|
|
|
|
|
assert profil.error and "FileNotFoundError" in profil.error
|
|
|
|
|
|
assert profil.rows == 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_prompt_names_columns_and_ranges(kurse):
|
|
|
|
|
|
text = to_prompt(profile_files([kurse]))
|
|
|
|
|
|
assert "kurse.csv: 3 Zeilen, 4 Spalten" in text
|
|
|
|
|
|
assert "Rendite (Zahl, von 6.9 bis 14.4" in text
|
|
|
|
|
|
assert "1 fehlend" in text
|
|
|
|
|
|
assert to_prompt([]) == ""
|