Skip to content
Maximilian Burr edited this page May 30, 2023 · 18 revisions

Tests

CurrentConverter

Das Interface CurrentConverter (Implementierung in SadCurrentConverter) stellt Methoden zur Verfügung, die zur Konvertierung digitaler oder analoger Werte anderer Smarthome-Systeme in Minecraft Redstone-Signalstärke (ein ganzzahliger Wert von 0 bis 15) und zurück genutzt werden können. Die Werte anderer Systeme (nachfolgend "Zustand") sind natürliche Zahlen mit angegebener Obergrenze.

Dabei sollen folgende Regeln eingehalten werden:

  1. 0 wird zu 0

  2. NUR 0 wird zu 0

  3. der höchstmögliche Zustand wird zur höchstmöglichen Signalstärke und umgekehrt.

  4. die restlichen Werte sollen möglichst linear interpoliert werden, ohne die anderen Regeln zu verletzen.

Um die Einhaltung einiger dieser Regeln sicherzustellen, wurden Testfälle geschrieben. Zunächst exisitieren verschiedene Tests, die das Übergeben ungültiger Werte (z.B. negative Werte oder Signalstärken über 15) sowie ungültiger Kombinationen von Werten (ein Zustand, der über dem angegebenen Limit liegt) testen. In diesem Fall wird das Werfen einer Exception erwartet.

Aktuell existieren nur Tests mit digitalen Zuständen. Dabei werden Regel 1 und 3 von vier Tests (2 für je zwei Richtungen) behandelt. Außerdem werden die direkten Nachbarn der Signalstärke 0 und 15, nämlich 1 und 14 sowie ein Wert dazwischen getestet. Dass Regel 4 stimmt, wird also nur angenommen. Basierend auf dieser Annahme lässt sich jedoch die Einhaltung von Regel 2 schlussfolgern, da durch die Prüfung der direkten Nachbarn von 0 und 15 kein Zustand, der wie 0 nicht dazwischen liegt, mehr erreicht werden kann.

Plugin Factory

Die PluginFactory die im Bridge Programmteil verwendet wird soll nur Instanzen der Plugins instanziieren, wenn sie das IPlugin Interface implementieren. Die PluginFactory prüft ob die Klasse dem Interface IPlugin zuordenbar ist. Wenn sie zuordenbar ist wird eine Instanz der Klasse erstellt. Um zu testen, ob die createPluginMethode der PluginFactory das erwünschte Verhalten zeigt, wurde in PluginFactoryTest diese Implementierung der PluginFactory mit Unit Tests getestet.

Dabei wurden 2 Testäflle definiert:

  • createPlugin mit inkorrekter Klasse aufgerufen
  • createPluginmit korrekter Klasse aufgerufen

Mocking

Zum Hinzufügen und Entfernen von Geräten im Minecraft Smarthome werden Befehle verwendet, die im Spielchat eingegeben werden. Das Interface MinecraftCommandArgumentParser, das von der Klasse SadMinecraftCommandArgumentParser implementiert wird, stellt Methoden zur Konvertierung der Argumente des Befehls zu intern verwendeten Datentypen zur Verfügung. In SadMinecraftCommandArgumentParserTest wird diese Implementierung getestet. Zur Instantiierung des Parsers werden eine BlockIdentifierFactory und eine WorldIdentifierFactory per Dependency Injection benötigt. Beim Aufruf der Methode extractBlockIdentifier wird außerdem eine MinecraftCommandSource als Parameter erwartet. Zum Testen müssen diese Objekte gemockt werden. Diese drei Interfaces werden daher von drei handgeschriebenen Dummy-Klassen in der Test-Klasse implementiert.

Mit der Methode getWorldIdentifier in MinecraftCommandSource kann (durch Prüfung des Optional) erkannt werden, ob der Absender implizit eine Minecraft-Welt spezifiziert (z.B. da er sich darin aufhält). Dies ist der Fall bei Spielern, die einen Befehl ausführen, nicht aber wenn der Befehl von der Server-Konsole kommt. In diesem Fall wird die Angabe der Welt, ein sonst optionaler Parameter des Befehls zum Hinzufügen von Geräten, obligatorisch. Entsprechend gibt es zwei Methoden getDummyCommandSourceNotInAWorld und getDummyCommandSourceInWorldy in der Test-Klasse, die Mock-Objekte erzeugen, die vorgeben, in einer Welt zu sein oder eben nicht.

Die beiden anderen Dummy-Klassen sind ähnlich umgesetzt und ahmen das Verhalten nach, von dem bei den wirklichen Klassen (die hier ja nicht getestet werden sollen) ausgegangen wird.

Einhaltung der ATRIP-Regeln

Automatic

Die Tests sind automatisiert. Das bedeutet, dass sie im normalen Build Prozess mitausgeführt werden und dieser abgebrochen wird, falls mindestens ein Test fehlschlägt. Selbst ohne Vorwissen des Programmierers zieht ein Build nach einer potentiellen Änderung am Code somit ein Durchlaufen aller Tests nach sich, das nur im Fehlerfall "meckert".

Thorough

Die Tests sind nicht wirklich gründlich, da nur für wenig Code Tests geschrieben wurden. Die Funktionalitäten, die getestet wurden, sind dafür gründlich getestet. In der Beschreibung der geschriebenen Tests und im Abschnitt Test Coverage wird näher darauf eingegangen.

Repeatable

Die Tests sind wiederholbar. Nach dem Durchlauf der Tests sind keine Zustände verändert worden, somit wird kein Einfluss auf zukünftige Testdurchläufe genommen. Die Tests sind außerdem unabhängig von Zeit und Zufall.

Independent

Die Tests sind unabhängig voneinander, da alle benötigten Startzustände in jedem Test erneut hergestellt und nicht von bereits gelaufenen Tests wiederverwendet werden.

Professional

Die Tests sind nach größtenteils simpel gehalten. Die Methoden und Dummy-Klassen bei den Tests mit Mocking verbergen ein Stück weit Komplexität. Dabei wurde jedoch versucht, sprechende Namen für Methoden und auch Konstanten zu wählen, sodass ein Verständnis des Test-Codes möglichst leicht fällt. Die Auslagerung wurde als sinnvoll erachtet, da sonst viel Code wiederholt werden müsste und ein nachträgliches Ändern der Anforderungen und damit auch der Tests wesentlich aufwändiger würde.

Test Coverage

Da die Tests leider nur nachträglich erstellt wurden, um den Anforderungen der Prüfungsleistung zu entsprechen, ist die Test Coverage nicht sehr hoch.

Die Test Coverage der Smarthome Bridge und des Minecraft Smarthomes wurde zunächst einzeln mit dem jacoco-maven-plugin berechnet.

Zunächst die Ergebnisse für das Minecraft Smarthome:

![Test Coverage](images/Minecraft Smarthome Test Coverage.png)

Die Test Coverage nach Statements beträgt also 6%, die Coverage nach Verzweigungen 8%.

Da die Tests nicht gleichmäßig über die Codebasis verteilt sind, sondern stattdessen nur zwei Klassen getestet wurden, ist auch die Coverage für diese beiden Klassen von Interesse. Zum einen für SadCurrentConverter:

Test Coverage SadCurrentConverter

Und außerdem SadMinecraftCommandArgumentParser:

Test Coverage SadMinecraftCommandArgumentParser

Sämtliche missed Instructions und Branches betreffen hier ausschließlich Fehlerbehandlung des zu testenden Codes.

int to = (int) Math.round(convertInternal(from, maxFrom, maxTo));
if (to < 1 || maxTo < to) {
    throw new PluginException("We have verkackt");
}

Eine Verzweigung insbesondere soll nie ausgeführt werden und weist im Fall, dass sie betreten wird, nur darauf hin, dass der Code direkt davor nicht korrekt arbeitet. Sie ist sogesehen ein Laufzeit-Test und sollte daher eher in den Unit Tests sein oder zumindest mit einem ein assert- und kein if-Statement sein.

Clone this wiki locally