-
Notifications
You must be signed in to change notification settings - Fork 0
/
testing.tex
115 lines (97 loc) · 5.31 KB
/
testing.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
\section{Testplanung}
Außerhalb von Modultests, welche in allen drei Komponenten durchgeführt wurden, wurden Systemtests durchgeführt.
Auf diese wird sich in diesem Abschnitt fokussiert.
Da alle Interaktionen der Hardware oder des Frontends über die API gehen müssen, steht diese bei der Planung und Betrachtung von Tests im Mittelpuntkt.
Zuerst wird ein Überblick gegeben, wie die Tests geschrieben werden und im Anschluss wird etwas näher auf die Testplanung eingegangen.
Die Tests werden im Stil von Akzeptanztests aus Behavior Driven Development in der Sprache Gherkin verfasst.
Dies hat den Grund, dass sich die Tests so einfacher formulieren und verstehen lassen.
Da sich diese Tests auch ausführen lassen, sofern alle Schritte implementiert sind, geht man hier in die Richtung einer ausführbaren Spezifikation.
Um das Verhalten der API leichter zu testen, wurde eine virtuelle Python Umgebung geschrieben, welche ein Greenhouse simuliert.
Diese Umgebung kann direkt aus den Tests genutzt werden, um der API Daten zu schicken und die Antworten dieser zu verifizieren.
Im folgenden wird die Planung der Tests und damit einhergehende Bildung der Äquivalenzklassen beispielhaft an API Tests vorgestellt.
\subsection{Registrieren von Geräten}
Wenn ein neuer Sensor oder ein neuer Aktor zu einem Greenhouse hinzugefügt wird, soll dies auch der API mitgeteilt werden.
Hierfür gibt es einen Endpunkt, mit dem man ein Gerät unter einem bestimmten Namen registrieren kann.
Dabei ergeben sich nur zwei Äquivalenzklassen: ,,ein Gerät mit diesem Namen existiert bereits'' (GE im folgenden) und ,,ein Gerät mit diesem Name existiert noch nicht'' (GNE im Folgenden):
\begin{center}
\small
\begin{tabular}{|c||c|c|}
\hline
Äquivalenzklasse&GE&GNE \\
\hline
Gültigkeit&Nicht Gültig&Gültig \\
\hline
Erwarteter Wert&HTTP 409&HTTP 201 \\
\hline
\end{tabular}
\end{center}
Eine Implementierung des Verhaltens der Klasse GE in der Sprache Gherkin könnte folgendermaßen aussehen:
\begin{figure}[H]
\begin{minted}[linenos]{gherkin}
Scenario: Creating a device with a name that already exists
Given a device with name soil_moisture exists
When I try to create a device with the name soil_moisture
Then the API should emit a negative response with HTTP code 409
\end{minted}
\label{lst:test_create}
\caption{Beispielhafte Testimplementierung in Gherkin}
\end{figure}
\subsection{Senden von Datenpunkten}
Da sich im letzten Beispiel nur zwei Äquivalenzklassen ergaben, welche sich nicht kombinieren lassen, wird im Folgenden ein etwas komplizierteres Beispiel betrachtet.
Beim Senden von Datenpunkten muss wieder der Name eines Geräts angegeben werden, jedoch muss überprüft werden ob das Gerät vom Typ Sensor ist.
Dies hat den Grund, dass Daten nur von Sensoren gesendet werden dürfen.
Hierbei ergeben sich folgende Äquivalenzklassen: ,,ein Gerät mit dem Namen existiert'' (GE), ,,ein Gerät mit dem Namen existiert nicht'' (GNE), ,,das Gerät ist vom Typ Sensor'' (TS) ,,und das Gerät ist nicht vom Typ Sensor'' (NTS).
Diese Äquivalenzklassen lassen sich nun auf folgende Weisen kombinieren:
\begin{center}
\begin{tabular}{c||c|c}
&TS&NTS\\
\hline
\hline
GE&GE+TS&GE+NTS\\
\hline
GNE& \multicolumn{2}{c}{GNE}\\
\end{tabular}
\end{center}
Die unteren Beiden kombinierten Einträge können zu einem Eintrag zusammengefasst werden, da die Überprüfung nach Existenz wichtiger ist als nach richtigem Typ.
Falls kein Gerät mit diesem Namen existiert, ist die Information, ob es vom richtigen Typ ist, überflüssig.
Für die zusammengesetzten Äquivalenzklassen kann man nun die Gültigkeit und die erwarteten Werte erfassen:
\begin{center}
\begin{tabular}{|c||c|c|c|}
\hline
Äquivalenzklasse&GE+TS&GE+NTS&GNE\\
\hline
Gültigkeit&Gültig&Nicht Gültig&Nicht Gültig\\
\hline
Erwarteter Wert&HTTP 200&HTTP 422&HTTP 409\\
\hline
\end{tabular}
\end{center}
Eine mögliche Implementierung eines Tests zur Äquivalenzklasse GE+NTS könnte folgendermaßen aussehen:
\begin{figure}[H]
\begin{minted}[linenos]{gherkin}
Scenario: A device of type actuator tries to record a datapoint
Given a device with name lamp exists
And the device is of type actuator
When the device tries to record a datapoint
Then the API should emit a negative response with HTTP code 422
\end{minted}
\end{figure}
Die Schritte aus diesem Test sind per Parametrisierung wiederverwendbar gestaltet um in den Tests für die anderen Äquivalenzklassen erneut benutzt werden zu können.
Eine vereinfachte Implementierung der Schritte könnte folgendermaßen aussehen:
\begin{figure}[H]
\begin{minted}[linenos]{python}
@given("A device {device_name} exists")
def ensure_device_exists(device_name: str):
assert(greenhouse.has_device("lamp"))
context.device = greenhouse.get_device("lamp")
@given("the device is of type {device_type}")
def ensure_device_is_of_type(device_type: str):
assert(context.device.type == DeviceType.ACTUATOR)
@when("the device tries to record a datapoint")
def device_record_datapoint():
context.response = greenhouse.record_datapoint(context.device)
@then("the API should emit a {} response with code {code})
def api_should_respond_with(code: int):
assert(context.response.code == code)
\end{minted}
\end{figure}