import os import torch import pytest from unittest.mock import patch from cognitive_mapping_probe.llm_iface import get_or_load_model from cognitive_mapping_probe.resonance_seismograph import run_silent_cogitation_seismic from cognitive_mapping_probe.utils import dbg, DEBUG_ENABLED # --- Tests for llm_iface.py --- @patch('cognitive_mapping_probe.llm_iface.AutoTokenizer.from_pretrained') @patch('cognitive_mapping_probe.llm_iface.AutoModelForCausalLM.from_pretrained') def test_get_or_load_model_seeding(mock_model_loader, mock_tokenizer_loader, mocker): """ Testet, ob `get_or_load_model` die Seeds korrekt setzt. Wir mocken hier die langsamen `from_pretrained`-Aufrufe. """ # Mocke die Rückgabewerte der Hugging Face Ladefunktionen mock_model = mocker.MagicMock() mock_model.eval.return_value = None mock_model.set_attn_implementation.return_value = None mock_model.config = mocker.MagicMock() mock_model.device = 'cpu' mock_model_loader.return_value = mock_model mock_tokenizer_loader.return_value = mocker.MagicMock() # Mocke die globalen Seeding-Funktionen, um ihre Aufrufe zu überprüfen mock_torch_manual_seed = mocker.patch('torch.manual_seed') mock_np_random_seed = mocker.patch('numpy.random.seed') seed = 123 get_or_load_model("fake-model", seed=seed) # ASSERT: Wurden die Seeding-Funktionen mit dem korrekten Seed aufgerufen? mock_torch_manual_seed.assert_called_with(seed) mock_np_random_seed.assert_called_with(seed) # --- Tests for resonance_seismograph.py --- def test_run_silent_cogitation_seismic_output_shape_and_type(mock_llm): """ Testet die Kernfunktion `run_silent_cogitation_seismic`. ASSERT: Gibt eine Liste von Floats zurück, deren Länge der Anzahl der Schritte entspricht. """ num_steps = 10 state_deltas = run_silent_cogitation_seismic( llm=mock_llm, prompt_type="control_long_prose", num_steps=num_steps, temperature=0.7 ) assert isinstance(state_deltas, list) assert len(state_deltas) == num_steps assert all(isinstance(delta, float) for delta in state_deltas) assert all(delta >= 0 for delta in state_deltas) # Die Norm kann nicht negativ sein @pytest.mark.parametrize("num_steps", [0, 1, 100]) def test_run_silent_cogitation_seismic_num_steps(mock_llm, num_steps): """ Testet den Loop mit verschiedenen Anzahlen von Schritten. ASSERT: Die Länge der Ausgabe entspricht immer `num_steps`. """ state_deltas = run_silent_cogitation_seismic( llm=mock_llm, prompt_type="control_long_prose", num_steps=num_steps, temperature=0.7 ) assert len(state_deltas) == num_steps # --- Tests for utils.py --- def test_dbg_enabled(capsys): """ Testet die `dbg`-Funktion, wenn Debugging aktiviert ist. ASSERT: Die Nachricht wird auf stderr ausgegeben. """ # Setze die Umgebungsvariable temporär os.environ["CMP_DEBUG"] = "1" # Wichtig: Nach dem Ändern der Env-Variable muss das Modul neu geladen werden, # damit die globale Variable `DEBUG_ENABLED` aktualisiert wird. import importlib from cognitive_mapping_probe import utils importlib.reload(utils) utils.dbg("test message", 123) captured = capsys.readouterr() assert "[DEBUG] test message 123" in captured.err def test_dbg_disabled(capsys): """ Testet die `dbg`-Funktion, wenn Debugging deaktiviert ist. ASSERT: Es wird keine Ausgabe erzeugt. """ # Setze die Umgebungsvariable auf "deaktiviert" if "CMP_DEBUG" in os.environ: del os.environ["CMP_DEBUG"] import importlib from cognitive_mapping_probe import utils importlib.reload(utils) utils.dbg("this should not be printed") captured = capsys.readouterr() assert captured.out == "" assert captured.err == "" # Setze den Zustand zurück, um andere Tests nicht zu beeinflussen if DEBUG_ENABLED: os.environ["CMP_DEBUG"] = "1" importlib.reload(utils)