Unit Testing Nebeneffekt-schwerer Code


10

Ich fange an, C ++ - Code zu schreiben, um einen Roboter auszuführen, und ich weiß nicht, wie ich Unit-Tests integrieren soll, wenn ich das kann. Ich habe eine Bibliothek erhalten, mit der "Befehle" für den Roboter erstellt werden können, die automatisch geplant und ausgeführt werden. Der Mechanismus dieser Befehle zu erstellen , ist eine Befehlsbasisklasse bieten sie Unterklasse und der Implementierung von virtuellen void Initialize(), void Execute()und void End()Methoden. Diese Funktionen werden nur wegen ihrer Nebenwirkungen ausgeführt, die dem Roboter etwas antun (Motoren laufen lassen, Kolben ausfahren usw.). Aus diesem Grund sehe ich nirgendwo etwas, um Unit-Tests an den Code anzuhängen, ohne die gesamte Bibliothek zu verspotten, damit ich die virtuellen Vorher- und Nachher-Zustände des Roboters überprüfen kann. Gibt es eine Möglichkeit, dies zu testen, die nicht übermäßig belastend ist?

Bearbeiten

Ich glaube, ich habe mich über die Funktionalität der Bibliothek irregeführt. Die Bibliothek bietet den größten Teil der Schnittstelle zum Roboter sowie das Befehls- / Planungssystem. Es ist also nicht so einfach wie das Verspotten der Befehlsbasisklasse, sondern ich müsste die gesamte Schnittstelle zur Hardware verspotten. Ich habe leider einfach nicht die Zeit dazu.


Ich gehe davon aus, dass Sie jede Aktion, die Sie von Ihrem Roboter ausführen lassen, rückgängig machen können, oder? Können Sie die Aktionen Ihres Tests nicht rückgängig machen?
Neil

1
Es ist schade, dass die Bibliothek keine Komposition anstelle von Vererbung verwendet hat, da Sie die Befehlsklasse nur verspotten könnten, wenn dies der Fall wäre.
Robert Harvey

@Neil Ich bin mir nicht ganz sicher, was du fragst. Können Sie Ihre Frage umformulieren?
Will Kunkel

Antworten:


7

In diesem Fall würde ich meine eigene RobotControl-Schnittstelle mit Methoden einführen, die denen in der realen Bibliothek entsprechen.

Nachdem ich dies getan habe, würde ich eine RobotControlImpl-Klasse erstellen, die diese Schnittstelle gegen die reale Roboterbibliothek implementiert.

Die Befehle, die ich folglich schreiben würde, würden die Basisklasse nicht erweitern, sondern auf der von Ihnen eingeführten Schnittstelle arbeiten.

Auf diese Weise können Sie RobotControl verspotten, das Verspotten an einen beliebigen Befehl übergeben und überprüfen, ob die richtigen Methoden auf der Schnittstelle aufgerufen wurden.

In prod würden Sie das eigentliche Impl von RobotControl an die von Ihnen implementierten Befehle übergeben.

Ich bin mir nicht sicher, ob Sie dies im Sinn hatten und als umständlich betrachteten?

Bearbeiten: Oh, und wenn Sie erwarten, dass die Befehle in den Ruhezustand versetzt werden, um auf den Abschluss zu warten (Albtraum, aber manchmal ist dies das, was Sie haben), würde ich die Befehle benötigen, um eine Schlafmethode in RobotControl aufzurufen. Auf diese Weise können Sie den Ruhezustand während des Tests deaktivieren und nur überprüfen, ob der Befehl versucht, den Ruhezustand zu aktivieren.


2
+1. Gefällt dir die Schnittstelle nicht? Mach dein eigenes.
Neil

Das hört sich so an, als würden Sie vorschlagen, dass ich die ganze Bibliothek verspotte. Fast alle Funktionen, die die Befehle aufrufen, befinden sich in der Bibliothek.
Will Kunkel

0

Ich denke, es ist möglich, den Code auf minimal invasive Weise testbar zu machen. Damit meine ich, dass Sie die Befehle genau so schreiben können, wie es die Autoren der Roboterbibliothek beabsichtigt haben. Dies kann vorteilhaft sein, wenn Sie Code mit anderen austauschen möchten, die Ihre Zwischenschicht nicht verwenden.

Es ist ein separater "Unit Test Build" Ihres Codes erforderlich.

Sie überprüfen in einer zentralen Header-Datei anhand einer Kompilierungszeit, ob dies der Unit-Test-Build ist, und definieren in diesem Fall den Namen der Basisklasse und möglicherweise einiger anderer Klassen in der Roboterbibliothek in Namen von Klassen Ihrer Testimplementierung. Sie sollten dieselben virtuellen Funktionen wie in der Roboterbibliothek definieren und Stubs für Methoden bereitstellen, die Sie auf dem Roboter aufrufen.

Dann haben Sie Befehle, die Sie in Ihr eigenes Testframework einfügen können, das dieselben Methoden aufruft, die die Roboterbibliothek ausführen würde.

Dies erfordert ein gewisses Maß an Stubbing und Verspottung, aber das ist bei jedem Unit-Test-Design unvermeidlich.

Das Ändern des Basisklassennamens kann mit einem #define oder wahrscheinlich einem Typedef erfolgen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.