diff --git a/api.py b/api.py index 11cd1a7fa73e0b89c9e3e5c1699484b4ac90dbab..5ab82ad2f148f64d2967e945cdb0924568cb5de1 100644 --- a/api.py +++ b/api.py @@ -15,16 +15,21 @@ def drive_rover(): Endpunkt zum Steuern des Rovers. Erwartet ein JSON mit dem Schlüssel "Input", der die Befehlssequenz enthält. Gibt die erfolgreich ausgeführten Befehle zurück. - """ - data = request.get_json() - - if not data or 'Input' not in data: - return jsonify({'error':'Ungültige Anfrage. "Input" fehlt.'}), 400 - commands = data['Input'] - result = rover.drive(commands) - - return jsonify({'executed_commands':result}) + Entspricht der OpenAPI-Spezifikation in rest.txt + """ + try: + data = request.get_json() + + if not data or 'Input' not in data: + return jsonify({'error': 'Missing or invalid input'}), 400 + + commands = data['Input'] + result = rover.drive(commands) + + return jsonify({'output': result}) + except Exception as e: + return jsonify({'error': str(e)}), 400 if __name__ == '__main__': app.run(debug=True) diff --git a/mission_control.py b/mission_control.py index 891e6dc9159a73d1a662cd8b90d75d43c883e35e..5a1870df812883939e151c1a2468cccd57cdf3e1 100644 --- a/mission_control.py +++ b/mission_control.py @@ -51,7 +51,7 @@ class MissionControl: if response.status_code == 200: result = response.json() - return result['executed_commands'] + return result['output'] else: return f"Fehler: {response.status_code}, {response.text}" except Exception as e: diff --git a/test_api.py b/test_api.py new file mode 100644 index 0000000000000000000000000000000000000000..8e45eec862750c975f555c9b4a39e7c5d164f171 --- /dev/null +++ b/test_api.py @@ -0,0 +1,106 @@ +import unittest +import json +from unittest.mock import patch +from api import app, rover + +class TestDriveEndpoint(unittest.TestCase): + """Testfälle für den /drive Endpunkt basierend auf der OpenAPI-Spezifikation""" + + def setUp(self): + self.app = app.test_client() + self.app.testing = True + # Rover zurücksetzen für jeden Test + rover.Position = (0, 0) + rover.heading = 0 + + def test_forward_backward_commands(self): + """Test für Vorwärts- und Rückwärtsbefehle (FFFFBBB)""" + response = self.app.post('/drive', + data=json.dumps({'Input': 'FFFFBBB'}), + content_type='application/json') + self.assertEqual(response.status_code, 200) + data = json.loads(response.data) + self.assertIn('executed_commands', data) + + def test_simple_command_string(self): + """Test für einfache Befehlsfolge (FB)""" + response = self.app.post('/drive', + data=json.dumps({'Input': 'FB'}), + content_type='application/json') + self.assertEqual(response.status_code, 200) + data = json.loads(response.data) + self.assertIn('executed_commands', data) + + def test_alternating_directions(self): + """Test für alternierende Richtungen (RRRRLLLL)""" + response = self.app.post('/drive', + data=json.dumps({'Input': 'RRRRLLLL'}), + content_type='application/json') + self.assertEqual(response.status_code, 200) + data = json.loads(response.data) + self.assertIn('executed_commands', data) + + def test_mixed_commands_with_invalid_at_end(self): + """Test für gemischte Befehle mit ungültigem Befehl am Ende (FBRLX)""" + response = self.app.post('/drive', + data=json.dumps({'Input': 'FBRLX'}), + content_type='application/json') + self.assertEqual(response.status_code, 200) + data = json.loads(response.data) + self.assertIn('executed_commands', data) + # Prüfen, dass nur die gültigen Befehle ausgeführt wurden + self.assertEqual(data['executed_commands'], 'FBRL') + + def test_unknown_command_at_start(self): + """Test für unbekannten Befehl am Anfang (XFB)""" + response = self.app.post('/drive', + data=json.dumps({'Input': 'XFB'}), + content_type='application/json') + self.assertEqual(response.status_code, 200) + data = json.loads(response.data) + self.assertIn('executed_commands', data) + # Prüfen, dass nur die gültigen Befehle ausgeführt wurden + self.assertEqual(data['executed_commands'], 'FB') + + def test_missing_input(self): + """Test für fehlenden Input""" + response = self.app.post('/drive', + data=json.dumps({}), + content_type='application/json') + self.assertEqual(response.status_code, 400) + data = json.loads(response.data) + self.assertIn('error', data) + + def test_invalid_json(self): + """Test für ungültiges JSON""" + response = self.app.post('/drive', + data="This is not JSON", + content_type='application/json') + self.assertEqual(response.status_code, 400) + + def test_obstacle_detection(self): + """Test für Hinderniserkennung""" + # Hindernis bei (1,1) hinzufügen + rover.add_obstacle(1, 1) + # Versuchen, zum Hindernis zu fahren (von (0,0) nach Norden) + response = self.app.post('/drive', + data=json.dumps({'Input': 'FR'}), + content_type='application/json') + self.assertEqual(response.status_code, 200) + data = json.loads(response.data) + self.assertIn('executed_commands', data) + + def test_out_of_bounds(self): + """Test für Bewegung außerhalb der Grenzen""" + # Versuchen, außerhalb der Grenzen zu fahren + response = self.app.post('/drive', + data=json.dumps({'Input': 'FFFFFFFFFFFFFFFFFFF'}), + content_type='application/json') + self.assertEqual(response.status_code, 200) + data = json.loads(response.data) + self.assertIn('executed_commands', data) + # Die Anzahl der ausgeführten Befehle sollte kleiner sein als die Anzahl der gesendeten + self.assertLess(len(data['executed_commands']), 20) + +if __name__ == '__main__': + unittest.main()