Ich bin Mitglied des Robotikclubs meiner High School und für die Programmierung des Roboters verantwortlich. Ein Vorschlag, den ich immer wieder von Erwachsenen höre, ist, dass ich Unit-Tests schreiben sollte, um meinen Code zu validieren. Die Codebasis wird immer größer, und ich stimme zu, dass Unit-Tests sehr hilfreich wären, um Fehler schneller zu erkennen.
Ich bin mir jedoch nicht ganz sicher, wie ich das erreichen könnte. Meines Wissens wird ein Unit-Test durchgeführt, indem eine Funktion (oder ein Teilsystem des Codes) einer Reihe von Eingaben zugeführt wird, um sicherzustellen, dass jedes Mal dieselbe Ausgabe ausgegeben wird. Der Code, den ich derzeit habe, verarbeitet keine großen Datenmengen, sondern bearbeitet die Hardwarekomponenten des Roboters direkt. Die meiste Komplexität entsteht dadurch, dass sichergestellt wird, dass die Elektronik einwandfrei ist, der Code im Moment mit der tatsächlichen Hardware des Roboters übereinstimmt usw. Oft kann ich nur feststellen, ob es ein Problem gibt, indem ich den Code in den Roboter selbst lade. und versuchen, es auszuführen.
Wie können Komponententests für Code geschrieben werden, mit dem ein mechanisches Gerät bedient werden kann? Es scheint mir, dass Sie Fehler nur feststellen können, wenn Sie den Betrieb der Maschine beobachten.
Oder missverstehe ich nur, wie Unit-Tests funktionieren sollten?
( Wenn es darauf ankommt, hier ist der Code , er ist in C ++ geschrieben und ich nehme an FRC teil. )
quelle
Ich kann mir ein paar Dinge vorstellen, die Sie berücksichtigen müssen. Die erste besteht darin, die Hardwarezugriffsebene so dünn wie möglich zu gestalten, selbst wenn dies das Erstellen einer grundlegenden Wrapper-Ebene für diese Ebene bedeutet. Dies bietet Ihnen einige Vorteile. Das erste ist, dass Sie das hardwarespezifische Verhalten Ihres Codes vom Hardwarezugriff selbst isolieren können, was bedeutet, dass Sie alles bis zum Ende Ihrer Hardwarekommunikation testen können, ohne auf die Hardware selbst zugreifen zu müssen.
Wenn Sie beispielsweise ein I2C-basiertes Signalisierungsprotokoll entwerfen müssen, können Sie testen, ob Ihr Code die richtigen I2C-Signale generiert, ohne die Hardware in Ihre Tests einbinden zu müssen.
Bei Aufrufen der eigentlichen Hardware können Sie testen, ob sie sich richtig verhalten, indem Sie Ihre Hardwareebene verspotten. Hier zahlt es sich wirklich aus, eine sehr dünne Hardwareebene beizubehalten, da Sie Ihre Verspottung so reduzieren können, dass sie nur die erforderlichen Mindestfunktionen ausführt Adressieren Sie die Hardware tatsächlich, aber Sie müssen die einzelnen Signale nicht unbedingt selbst testen, da alle Ihre Signale auf einer höheren Ebene testbar sein sollten. Dies bedeutet, dass Sie mit Ihrem Mock überprüfen, ob Aufrufe an bestimmte Hardwaremethoden erfolgen, die dazu führen, dass Ihre Signale an die Hardware gesendet werden. Wenn Sie Ihre Hardware abfragen müssen, muss Ihr Mock in der Lage sein, nur Ereignisse oder Methoden in Ihrem Code auszulösen, da Ihre Rückmeldung wiederum auf einer höheren Ebene behandelt werden sollte.
Dies passt im Wesentlichen zu dem, was Oleksi in seiner Antwort gesagt hat , da es in der Regel mehr Arbeit ist, Dinge auf Hardware-Ebene zu verspotten. Es ist jedoch nicht so schwierig, wenn Sie sich an eine möglichst schlanke Minimal-Code- / Aufruf-Ebene halten, die Sie für die erstellen können Hardware.
Wenn Sie Code haben, der alle Tests besteht, müssen Sie noch eine Reihe manueller Tests durchführen, um sicherzugehen, dass Sie in Ihrer Hardware-Schicht alles richtig gemacht haben.
Die andere Sache, die neben dem Verspotten und dem Überlagern in den Sinn kommt, ist die Verwendung einer Test-First-Entwicklungspraxis. Im Wesentlichen codieren Sie Ihre Anforderungen als Testkriterien und stützen Ihre Implementierung auf Ihre Tests. Auf diese Weise können Sie sicherstellen, dass Sie Ihren Implementierungscode auf ein Minimum beschränken, und gleichzeitig sicherstellen, dass alle Ihre Testfälle Ihre Entwicklungsbemühungen vorantreiben. Indem Sie nicht zu viel Zeit für anderen potenziell nicht kritischen Code verschwenden, zu dem Sie möglicherweise "nur weil" verleitet werden, hilft test Ihnen, konzentriert zu bleiben, und erleichtert es Ihnen, Ihren Code beim Debuggen und bei der Verwendung zu ändern Ihrer Unit-Tests und Mocks. Das Debuggen von Softwarefehlern durch die Hardware ist bekanntermaßen kompliziert und beansprucht einen großen Teil Ihrer Zeit, den Sie besser für andere Aufgaben ausgeben würden.
quelle
Ich kann Ihnen sagen, wie sie es auf Flugsimulatoren machen
Erstens erhalten Sie nur die Hälfte der Antwort, wenn Sie diese Frage nur Programmierern stellen. Sie sollten sie daher wahrscheinlich auf http://electronics.stackexchange.com kreuzen, während Sie gerade dabei sind.
Ich habe noch keine Arbeit mit Robotern gemacht, aber ich habe 5 Jahre damit verbracht, Hardware für Flugsimulatoren zu entwickeln, damit ich Ihnen sagen kann, wie ihre Architektur funktioniert.
Die Hardware-Schicht ist dumm
Es enthält eine grundlegende Schnittstelle, über die Sie einfache Ein- / Ausgabewerte anpassen und Interpolations-Haltepunkte für analoge Signale festlegen können. Wenn Sie mit "frischer" Hardware arbeiten, funktioniert alles wie erwartet mit wenig oder keiner Kalibrierung, aber im Laufe der Zeit unterliegen die Teile einem mechanischen Verschleiß und müssen angepasst werden.
Die Kalibrierung ist eine einfache Tabelle, die aufgeteilte Werte zwischen den min / max-Werten enthält. Um die Eingabe an diesen zu messen, wird normalerweise ein Servo verwendet (z. B. ein lineares Potentiometer, ein Wandler, Beschleunigungsmesser usw.). Oder bei Instrumenten beurteilen Sie die Genauigkeit einfach visuell und stellen sie ein, bis sie kalibriert sind.
Die Softwareschicht ist das Gegenteil
Alles ist komplex und miteinander verbunden, daher ist es wichtig, einige Variablen zu isolieren, um die Funktionalität zu testen. Sie müssen sich keine Gedanken über Szenarien machen, da es viel einfacher ist, einige realistische Szenarien auszuführen, in denen Sie Daten sammeln können. Wenn Sie die Tests ausführen, messen Sie im Grunde genommen die gespeicherten Daten anhand der aktuellen Ausgabe.
In einem Flugsimulator wird dies als QTG (Qualification Test Guide) bezeichnet. Im Kern werden die Daten in einem 2D-Raster aufgezeichnet, wobei eine Dimension die Zeit und die andere die Ausgabe ist.
Ob Sie es glauben oder nicht, das ist das Wesentliche bei der Entwicklung der Modelle. Ein echtes Flugzeug ist mit einer Tonne Sensoren ausgestattet und wird in kontrollierten Szenarien herumgeflogen. Da alle Steuerungen ohne menschliche Interaktion gesteuert werden können, werden die Tests vom Computer ausgeführt (dh die Sim fliegt selbst) und die Daten werden verglichen.
Auch wenn die Robotik in einem ganz anderen Maßstab erstellt wird, sind die Prinzipien dieselben. Der traditionelle Ansatz besteht darin, die Hardware- und Softwareschichten vollständig zu trennen, damit beide einzeln getestet werden können. Hardware-Input wird über Servos gesammelt und über eine unabhängige Schnittstelle eingestellt. Der Software-Eingang kann eingestellt / gelesen werden, indem die Signalisierung, die sonst an die Hardware gesendet würde, unabhängig gemessen und verglichen und mit den bekannten "guten" Daten verglichen wird.
Die Tests selbst müssen nicht unbedingt komplex sein, solange die Ergebnisse vorhersehbar, messbar und reproduzierbar sind.
quelle
Wie bereits gesagt, verspotten Sie die Hardware-Teile und stumpfen Sie sie heraus. Wenn Sie beispielsweise eine Schnittstelle zum Roboter haben, können Sie diese Schnittstelle erben und dann einfache Stub-Implementierungen vornehmen. Dann können Sie testen, ob die Stub-Implementierung wie erwartet aufgerufen wurde. Wenn das erwartete Funktionen oder erwartete Parameter sind.
quelle