zusammenfassungen/Writerside/topics/04/Software Engineering/01_ImplementingForMaintainability.md
David Schirrmeister 1e27edf7cd update
2025-04-08 14:56:15 +02:00

7.5 KiB

Implementing for Maintainability

Motivation and Introduction

  • Unit und Integration Testing ist ein bekannter Ansatz um Qualität sicherzustellen
  • Gut-getestete Anwendungen:
    • 1 line of code = 1-3 lines of test code
    • kann auf bis zu 1:10 hochgehen
  • Produkt- und Testcode werden parallel geschrieben
  • guten Code schreiben ist schwer

Black-/White-Box Testing

image_555.png

Black-Box-Testing

Nur das Interface ist bekannt, nicht der Inhalt

  • Methode vom Software-Testing, das die Funktion analysiert, ohne den Mechanismus zu kennen
  • Normalerweise rund um die Spezifikationen und Anforderungen
    • Was soll die Anwendung tun, nicht wie tut sie es

White-Box-Testing

Das Interface und alle Mechanismen sind bekannt

  • Testmethodik, die verifiziert, wie die Anwendung arbeitet
  • Tests sind am Sourcecode ausgerichtet, nicht an den Anforderungen

Pros / Cons

  • White-Box-Testing ist systematischer und anspruchsvoller
    • Analyse des Codes kann zu Fehlerentdeckungen führen, die zuvor übersehen wurden
    • Testergebnisse sind oft spröde
      • Sind sehr verknüpft mit der Implementierung des Codes
      • Solche Tests produzieren viele false-positives und sind nicht gut für die Metrik der Resistenz gegen Refactoring
    • Können häufig nicht rückgeschlossen werden zu einem Verhalten, dass wichtig ist für eine Business-Person
      • Starkes Zeichen, dass die Tests nicht viel Wert hinzufügen
  • Black-Box-Testing hat gegensätzliche Vor-/Nachteile

Black-/White-Box-Testing sind Konzepte, die auf verschiedene Test-Typen angewendet werden können

Testing Quadrants Matrix

image_556.png

Quadrant 1: Technologie-fokussierte Tests, die das Development leiten

  • Developer Tests:

    • Unit tests
      • Verifizieren Funktionalität eines kleinen Subsets des Systems
    • Component-/Integration Tests:
      • Verifizieren Verhalten eines größeren Teils
  • Tests sind nicht für den Kunden

Unit Testing

  • Unit Tests sind die essenzielle Basis einer guten Test-Suite
    • Verglichen mit anderen, sind sie einfach zu erstellen und warten
    • Viele Unit-Tests :)

Goals of Testing during Implementation

Aktiviere nachhaltiges Wachstum des Software-Projekts

  • image_579.png
  • Nachhaltigkeit ist wichtig
    • Projektwachstum ist am Anfang einfach
    • Das Wachstum zu halten ist schwer
  • Tests können das nachhaltige Wachstum fördern
    • Aber: erfordern initialen, teilweise signifikanten Einsatz
  • Schlechte Tests bringen nichts
    • verlangsamen am Anfang schlechten Code
    • langfristig trotzdem ungünstig
  • Test Code ist Teil der Codebase
    • Teil, der ein spezifisches Problem behandelt - Anwendungsrichtigkeit sicherstellen
  • Kosten eines Tests
    • Wert
    • anstehende Kosten
      • Refactoring des Tests, wenn der Code refactored wird
      • Test bei jeder Codeänderung ausführen
      • Mit Fehlalarmen durch den Test umgehen
      • Zeit für das Verstehen des Tests, wenn man den zu testenden Code verstehen möchte

General Testing Strategy

Testing Automation Pyramid

image_580.png

  • Software Tests in 3 Kategorien aufteilen
    • UI-Tests
      • Testen die Anwendung durch Interaktion mit der UI
      • sehr high-level
    • Service Tests
      • Black-Box testen von größeren Softwareteilen
        • bspw. Komponenten, Services
    • Unit Tests
      • werden während Entwicklung von Developern geschrieben
  • Gibt Idee, wie viele Tests pro Kategorie in der Test-Suite sein sollten

Testing Ice Cream Cone

image_581.png

  • Style einer Test-Suite, die häufig in der Industrie verwendet wird
    • hohe Anzahl manueller, high-level Tests
    • end-to-end Tests (auch an UI), die automatisch ausgeführt werden können
    • nur wenige integration/unit tests
  • Tests Suite mit dieser Strategie ist nicht gut wartbar
    • manuelle Tests sind teuer und langwierig
    • automatisierte high-level Tests gehen häufig kaputt, sobald Änderungen in der Anwendung auftreten

Test Driven Development (TDD)

image_582.png

  1. Tests schreiben
    • Design
      • Akzeptanzkriterien für den nächsten Arbeitsschritt festlegen
      • Anregung lose gekoppelte Komponenten zu entwerfen
        • einfache Testbarkeit, dann verbinden
      • Ausführbare Beschreibung von dem was der Code tut
    • Implementierung
      • Vervollständigen einer regressiven Test-Suite
  2. Tests ausführen
    • Implementierung
      • Error erkennen, während der Kontext noch frisch ist
    • Design
      • Bewusstmachung, wann die Implementierung vollständig ist

Golden Rule of TDD: schreibe niemals neue Funktionalitäten ohne einen fehlschlagenden Test

Vorteile des TDD

  • signifikante Reduktion der Defekt-Rate
    • auf Kosten eines moderaten Anstiegs im initialen Development-Prozesses
  • Empirische Untersuchungen haben das noch nicht bestätigt
    • TDD hat aber zu Qualitätssteigerung des Codes geführt

Häufige Fehler beim TDD

  • Individuelle Fehler
    • Vergessen die Tests regelmäßig auszuführen
    • Zu viele Tests auf einmal schreiben
    • Zu große/grobe Tests schreiben
    • zu triviale Tests schreiben, die eh funktionieren
  • Team-Fehler
    • Nur partieller Einsatz
    • Schlechte Wartung der Test-Suite
    • Verlassene Test-Suite (nie ausgeführt)

Unit-Testing vs. Integration Testing

Unit Integration
kleiner Teil eines Verhaltens größere Portion Code

image_583.png

4 Typen von Produktions-Code

image_584.png

Dimensionen

Komplexität und Domain-Signifikanz
  • Code Komplexität
    • Definiert durch Nummer der Branching-Punkte im Code
    • if-statements, Polymorphismus
  • Domain-Signifikanz
    • Wie signifikant ist der Code für die problematische Domain
    • normalerweise Verbindung Domain-Layer-Code zu End-User-Ziele
      • Hohe Domain-Signifikanz
    • Bsp. für niedrige Relevanz: Utility Code
Nummer der Kollaborateure
  • Kollaborateur = Abhängigkeit, die veränderlich /& außerhalb des Prozesses ist
    • veränderlich
      • nicht nur read-only
    • außerhalb des Prozesses
      • häufig geteilt
      • hindert Tests an unabhängiger Ausführung
  • Code mit vielen Kollaborateuren ist schwer zu testen

Typen

Domain model & algorithms
  • Domain Code, wenige Kollaborateure
  • komplexer Code häufig Teil des Domain-Models
  • wenige Kollaborateure → Testbarkeit
  • sollte NIEMALS Abhängigkeiten außerhalb des Prozesses haben
Controllers
  • Wenig Domain Code, viele Kollaborateure
  • Koordination der Ausführung von Use-Cases für Domain-Klassen und externen Anwendungen
  • Keine komplexe / Business-kritische Arbeit selbst/allein machen
  • wenig Komplexität, wenig Domain-Signifikanz
  • Viele Abhängigkeiten außerhalb des Projekts
Overcomplicated Code
  • Viel Domain Code, viele Kollaborateure
  • ist aber auch komplex und wichtig
Trivialer Code
  • wenig Domain-Code, wenig Kollaborateure

Separierung von Controllers & DomainModel, Algorithmen

image_585.png

  • Separiert komplexen Code von Code, der Orchestrierung macht
    • Domain Code hat tiefe Implementierung in Business Logik
    • Controller haben breite Orchestrierung aber enge Komplexität
  • Erhöht Wartbarkeit und Testbarkeit

Wie testet man die 4 Typen?

image_587.png

  • trivialer Code muss nicht getestet werden