# -*- coding: utf-8 -*- """ Unit-Tests für VarioFoerderer (Refactored) Diese Tests können direkt in der Library-Methode verwendet werden oder als separate Test-Datei ausgeführt werden. """ import unittest import math from unittest.mock import Mock, MagicMock from VarioFoerderer import ( VarioFoerderer, Foerderrichtung, MotorUmlenkConfig, BogenDeltas, OffsetResult, _parse_delta_attribute, _calculate_offset_with_rotation, _is_es_as_element, horizontale_ausrichtung, ) class TestMotorUmlenkConfig(unittest.TestCase): """Tests für MotorUmlenkConfig Dataclass""" def test_motor_offset_berechnung(self): """Test: Motor-Offset-Berechnung""" config = MotorUmlenkConfig( winkel_motor=45.0, winkel_umlenk=30.0, umlenk_laenge=(100.0, 50.0), motor_laenge=(80.0, 40.0), vario_abstand=25.0 ) # Motor-Offsets expected_motor_x = 100.0 * math.cos(math.radians(45.0)) expected_motor_z = 100.0 * math.sin(math.radians(45.0)) self.assertAlmostEqual(config.motor_offset_x, expected_motor_x, places=5) self.assertAlmostEqual(config.motor_offset_z, expected_motor_z, places=5) def test_umlenk_offset_berechnung(self): """Test: Umlenk-Offset-Berechnung""" config = MotorUmlenkConfig( winkel_motor=45.0, winkel_umlenk=30.0, umlenk_laenge=(100.0, 50.0), motor_laenge=(80.0, 40.0), vario_abstand=25.0 ) # Umlenk-Offsets expected_umlenk_x = 80.0 * math.cos(math.radians(30.0)) expected_umlenk_z = 80.0 * math.sin(math.radians(30.0)) self.assertAlmostEqual(config.umlenk_offset_x, expected_umlenk_x, places=5) self.assertAlmostEqual(config.umlenk_offset_z, expected_umlenk_z, places=5) class TestBogenDeltas(unittest.TestCase): """Tests für BogenDeltas Dataclass""" def test_normalize_negative_values(self): """Test: Normalisierung negativer Werte""" deltas = BogenDeltas( SP_0=[-10.0, -20.0, 5.0], SP_1=[15.0, -25.0, 10.0], VP_0=[-5.0, 8.0, -3.0], VP_1=[12.0, -15.0, 7.0] ) deltas.normalize_negative_values() # X und Y (Index 0 und 1) sollen positiv sein, Z (Index 2) unverändert self.assertEqual(deltas.SP_0, [10.0, 20.0, 5.0]) self.assertEqual(deltas.SP_1, [15.0, 25.0, 10.0]) self.assertEqual(deltas.VP_0, [5.0, 8.0, -3.0]) self.assertEqual(deltas.VP_1, [12.0, 15.0, 7.0]) class TestVarioFoerderer(unittest.TestCase): """Tests für VarioFoerderer Modell""" def test_from_merkmale(self): """Test: VarioFoerderer aus Merkmale-Dict erstellen""" merkmale = { "Höhe Anfang": "1.5", "Höhe Ende": "2.0", "Länge in Meter": "5.0", "Winkel": "6", "Motorstation_hinten": True, "Spannstation_vorn": False, "Drehung": "-90", "Förderrichtung": "Auf", "Anzahl der Scanner": "2", "Anzahl der Separatoren": "3", } foerderer = VarioFoerderer.from_merkmale("TEST-001", 100.0, 200.0, merkmale) self.assertEqual(foerderer.teileid, "TEST-001") self.assertEqual(foerderer.x, 100.0) self.assertEqual(foerderer.y, 200.0) self.assertEqual(foerderer.h0, 1500.0) # 1.5 * 1000 self.assertEqual(foerderer.h1, 2000.0) # 2.0 * 1000 self.assertEqual(foerderer.laenge, 5000.0) # 5.0 * 1000 self.assertEqual(foerderer.winkel, 6.0) self.assertTrue(foerderer.hat_motor) self.assertFalse(foerderer.hat_umlenk) self.assertEqual(foerderer.drehung, -90.0) self.assertEqual(foerderer.foerderer_richtung, "Auf") self.assertEqual(foerderer.anzahl_scanner, 2) self.assertEqual(foerderer.anzahl_separatoren, 3) def test_hight_zwischen(self): """Test: Berechnung der mittleren Höhe""" merkmale = { "Höhe Anfang": "1.0", "Höhe Ende": "3.0", "Länge in Meter": "1.0", "Winkel": "3", "Motorstation_hinten": False, "Spannstation_vorn": False, "Drehung": "0", "Förderrichtung": "Auf", "Anzahl der Scanner": "0", "Anzahl der Separatoren": "0", } foerderer = VarioFoerderer.from_merkmale("TEST-002", 0, 0, merkmale) expected_height = (1000.0 + 3000.0) / 2 # (h0 + h1) / 2 self.assertEqual(foerderer.hight_zwischen, expected_height) class TestHilfsfunktionen(unittest.TestCase): """Tests für generische Hilfsfunktionen""" def test_parse_delta_attribute(self): """Test: Delta-Attribut parsen""" attrib_dict = { "DELTA_SP_0": "10.5;20.3;-5.7", "DELTA_VP_1": "15.2,25.8,-8.1" } result_sp = _parse_delta_attribute(attrib_dict, "DELTA_SP_0") result_vp = _parse_delta_attribute(attrib_dict, "DELTA_VP_1") self.assertEqual(result_sp, [10.5, 20.3, -5.7]) self.assertEqual(result_vp, [15.2, 25.8, -8.1]) def test_calculate_offset_with_rotation(self): """Test: Offset-Berechnung mit Rotation""" SP = [10.0, 5.0, 8.0] VP = [2.0, 5.0, 3.0] winkel = 45.0 result = _calculate_offset_with_rotation(SP, VP, winkel) # Erwartete Werte berechnen rad = math.radians(45.0) expected_x = (SP[0] - VP[0]) * math.cos(rad) + (SP[2] - VP[2]) * math.sin(rad) expected_y = VP[1] expected_z = -(SP[0] - VP[0]) * math.sin(rad) + (SP[2] - VP[2]) * math.cos(rad) self.assertAlmostEqual(result[0], expected_x, places=5) self.assertAlmostEqual(result[1], expected_y, places=5) self.assertAlmostEqual(result[2], expected_z, places=5) def test_is_es_as_element_true(self): """Test: ES/AS-Element erkennen""" entity = Mock() entity.dxftype.return_value = "INSERT" entity.dxf.name = "200000146_ES-Element_90_rechts_modified" self.assertTrue(_is_es_as_element(entity)) def test_is_es_as_element_false(self): """Test: Kein ES/AS-Element""" entity = Mock() entity.dxftype.return_value = "INSERT" entity.dxf.name = "Vario_Bogen_auf_12°" self.assertFalse(_is_es_as_element(entity)) def test_is_es_as_element_not_insert(self): """Test: Kein INSERT-Entity""" entity = Mock() entity.dxftype.return_value = "LINE" self.assertFalse(_is_es_as_element(entity)) class TestHorizontaleAusrichtung(unittest.TestCase): """Tests für horizontale_ausrichtung Funktion""" def test_horizontal_rotation_0(self): """Test: Horizontale Ausrichtung bei Rotation 0°""" merkmale = { "Höhe Anfang": "1.0", "Höhe Ende": "1.0", "Länge in Meter": "1.0", "Winkel": "3", "Motorstation_hinten": False, "Spannstation_vorn": False, "Drehung": "0", "Förderrichtung": "Horizontal", "Anzahl der Scanner": "0", "Anzahl der Separatoren": "0", } foerderer = VarioFoerderer.from_merkmale("TEST", 100.0, 200.0, merkmale) # Förderer ist über Kreisel (y > y_kreisel) result = horizontale_ausrichtung(foerderer, 100.0, 100.0) self.assertEqual(result, "unten_drehung_0_or_-90") # Förderer ist unter Kreisel (y < y_kreisel) result = horizontale_ausrichtung(foerderer, 100.0, 300.0) self.assertEqual(result, "oben_drehung_0_or_-90") def test_nicht_horizontal(self): """Test: Nicht-horizontale Förderer geben 'None' zurück""" merkmale = { "Höhe Anfang": "1.0", "Höhe Ende": "2.0", "Länge in Meter": "1.0", "Winkel": "6", "Motorstation_hinten": False, "Spannstation_vorn": False, "Drehung": "0", "Förderrichtung": "Auf", "Anzahl der Scanner": "0", "Anzahl der Separatoren": "0", } foerderer = VarioFoerderer.from_merkmale("TEST", 100.0, 200.0, merkmale) result = horizontale_ausrichtung(foerderer, 100.0, 100.0) self.assertEqual(result, "None") class TestFoerderrichtungEnum(unittest.TestCase): """Tests für Foerderrichtung Enum""" def test_enum_werte(self): """Test: Enum-Werte sind korrekt""" self.assertEqual(Foerderrichtung.AUF.value, "Auf") self.assertEqual(Foerderrichtung.AB.value, "Ab") self.assertEqual(Foerderrichtung.HORIZONTAL.value, "Horizontal") def test_enum_vergleich(self): """Test: Enum-Vergleich funktioniert""" richtung = "Auf" self.assertEqual(richtung, Foerderrichtung.AUF.value) # ============================================================================ # Test-Runner # ============================================================================ def run_tests(): """Führt alle Unit-Tests aus""" loader = unittest.TestLoader() suite = loader.loadTestsFromModule(__import__(__name__)) runner = unittest.TextTestRunner(verbosity=2) result = runner.run(suite) print("\n" + "="*70) print(f"Tests durchgeführt: {result.testsRun}") print(f"Erfolgreich: {result.testsRun - len(result.failures) - len(result.errors)}") print(f"Fehlgeschlagen: {len(result.failures)}") print(f"Errors: {len(result.errors)}") print("="*70) return result.wasSuccessful() if __name__ == "__main__": success = run_tests() exit(0 if success else 1)