Write about tests; Talk about separation of concerns;

This commit is contained in:
Leon Schoch
2023-09-01 16:11:39 +02:00
parent 4396406545
commit 0a0dd58c94
3 changed files with 92 additions and 2 deletions

View File

@@ -247,7 +247,16 @@ def generate_bird_files(v4_routes, v6_routes, pybird, pybird6):
\newpage
Die Methode \verb|bird_config|, welche um eine gute Struktur zu wahren zu einer gesonderten Datei und Klasse angehört, ruft die \verb|get_communities| Methode der Route Dataclass auf, um die Routen in einer von Bird lesbares Format zu wandeln.
Des Weiteren wird hier die tatsächliche Konfiguration auf das Dateisystem geschrieben.
Hier wurde das Prinzip des `Separation of Concerns` nicht eingehalten.
Im Idealfall sollte die Routenlogik und Birdlogik vollkommen voneinander getrennt sein.
Durch die Aufteilung des Codes in abgegrenzte Bereiche wird der Code übersichtlicher und leichter verständlich.
Entwickler können sich auf einen spezifischen Teil der Anwendung konzentrieren, ohne sich um die Komplexität anderer Teile kümmern zu müssen.
Dies erhöht die Wartbarkeit des Programmcodes um ein Vielfaches, da Änderungen eines Teiles wenig bis keinen Einfluss auf einen anderen haben.
Eine mögliche Lösung wäre hier, entweder die Communities schon vor der Übergabe an die Birdlogik in ein von Bird lesbares Format zu wandeln, oder dies in der Birdlogik selbst zu tun.
Dadurch dass die Birdlogik hier jedoch eine Methode aus der Routenlogik aufruft, wird unnötige Kopplung geschaffen.
Dies sollte in einer zukünftigen Revision des Codes gelöst werden.
Des Weiteren wird in der Birdlogik die tatsächliche Konfiguration auf das Dateisystem geschrieben.
\begin{lstlisting}[language=python,
frame=single, % Ein Rahmen um den Code
@@ -757,6 +766,86 @@ def write_emergency_file(routes: RouteContainer, emergency_route_file: str):
\section{Testen}
Unit-Testing ist ein essenzieller Bestandteil der Entwicklung des Route Injection Service.
Es dient dazu, die Qualität, Verlässlichkeit und Korrektheit des Codes sicherzustellen.
Dieser Abschnitt erläutert die Bedeutung und den Prozess des Unit-Testings für den entwickelten Service.
Die Verwendung von Unit-Tests bietet mehrere Vorteile.
Sie ermöglichen die frühzeitige Erkennung von Fehlern und Unstimmigkeiten im Code.
Darüber hinaus dienen sie als Form der Dokumentation und unterstützen Refactoring-Bemühungen, um sicherzustellen, dass Änderungen den erwarteten Verhalten nicht beeinträchtigen.
Unit-Tests schaffen Vertrauen in die Software, da sie Fehler und Probleme offenlegen, bevor sie zu potenziell schwerwiegenden Problemen werden können.
Im Fall des Route Injection Service wurde das pytest als Testwerkzeug eingesetzt.
Die Testabdeckung ist von zentraler Bedeutung, da sie sicherstellt, dass jeder relevante Teil des Codes getestet wird.
Über den gesamten Route Injection Service wurde hier eine Codeabdeckung von 97\% erreicht.
Die Automatisierung von Unit-Tests gewährleistet, dass Tests konsistent und wiederholbar durchgeführt werden können.
Dies ist besonders wichtig, wenn Codeänderungen vorgenommen werden, da Tests automatisch in die CI/CD-Pipeline integriert werden und bei jeder Änderung ausgeführt werden.
Zusätzlich zur Testautomatisierung wird ein Testbericht erstellt, welcher als Artifact in GitLab hochgeladen wird.
Dies ermöglicht es auch in Zukunft, vergangene Testergebnisse nachvollziehen zu können.
Unit Testing ist ein fortlaufender Prozess, der die Qualität und Stabilität des Route Injection Service sicherstellt.
Die regelmäßige Aktualisierung und Erweiterung der Test Suite ist unerlässlich, um sicherzustellen, dass der Service den sich ändernden Anforderungen gerecht wird und robust bleibt.
Insgesamt trägt das Unit Testing maßgeblich zur Zuverlässigkeit und Leistungsfähigkeit des Route Injection Service bei.
Die Überprüfung der Funktionalität einer einzelnen Methode ist eines der Hauptaufgaben von Unit-Testing.
Da viele Methoden jedoch voneinander oder anderen Komponenten abhängig sind, müssen diese über `Mockings` ersetzt werden.
Mittels der Python `unittest` Bibliothek ist dies sehr einfach möglich.
\newpage
Beim Erstellen der Tests wurde nach der \ac{AAA} Struktur gearbeitet.
\begin{lstlisting}[language=python,
frame=single, % Ein Rahmen um den Code
framexleftmargin=15pt, % Rahmen link von den Zahlen
style=algoBericht,
label={lst:test-respond-state-to-consul},
captionpos=b, % Caption unter den Code setzen
caption={Test für respond\_state\_to\_consul Methode}]
class TestRespondStateToConsul(TestCase):
@mock.patch("injector.PyBird")
@mock.patch("injector.get_bird_communities")
@mock.patch("injector.ckv")
def test_respond_state_to_consul(
self, mock_consul, mock_get_bird_communities, mock_pybird
):
mock_pybird.get_routes.return_value = [
{
"community": "47147:3200 12345:12345",
"prefix": "1.1.1.1/32",
}
]
mock_get_bird_communities.return_value = ["47147:3200", "12345:12345"]
route = Route(
prefix="1.1.1.1/32",
encode="IPv4",
communities='{"communities": ["47147:3200", "12345:12345"]}',
)
injector_id = "0"
respond_state_to_consul(mock_consul, mock_pybird, route, injector_id)
mock_consul.kv.put.assert_called_once_with(
f"v1/state/{injector_id}/IPv4/1.1.1.1_32",
'{"communities": ["47147:3200", "12345:12345"]}',
)
\end{lstlisting}
Die Mockings werden hier als Decorator übergeben, da die Methode anderen Methoden des Injectors aufruft und externe Abhängigkeiten wie die Consul oder Pybird Bibliothek besitzt.
\textbf{Arrange (Vorbereiten):}
In Zeile 8--21 werden die Rückgabewerte der Mockings und Parameter der zu überprüfenden Methode festgelegt.
\textbf{Act (Ausführen):}
In Zeile 22 wird die zu überprüfende Methode aufgerufen.
\textbf{Assert (Überprüfen):}
In Zeile 24--27 wird das tatsächliche Ergebnis mit dem zu erwartenden Ergebnis überprüft.
Wenn die Ergebnisse ungleich sind, schlägt der Test und somit auch die Pipeline in Gitlab fehl.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\endinput