Block 05 · Testen & Qualitätssicherung

Immer 8/9 Prüfungen · Ø 21 von 200 Punkten · Teil 1 (7×) + Teil 2 (6×) · in Teil 2 oft eine ganze 20–25-Punkte-Aufgabe (S23, S24, W25) · Lösungen: 05_Testen_QS_Loesungen.html
So arbeitest du mit diesem Block Erst den Erklärungssatz lesen, dann die Aufgaben mit dem Belegsatz daneben lösen (Belegsatz am besten separat ausdrucken und neben die Aufgaben legen – dort stehen die Code-Listings, die Spezifikationen und der englische Fachtext). Zeitrichtwert: 1 Punkt ≈ 0,9 Minuten. Lösungen erst danach in der separaten Lösungsdatei nachsehen. Zu jeder Code- und Unit-Test-Aufgabe gibt es dort den JUnit-5-Code und eine lauffähige Java-Datei im Ordner java\05_Testen_QS\.

A · Erklärungssatz

Testen und Qualitätssicherung kommen in 8 von 9 Prüfungen vor, und zwar auf zwei Arten: In Teil 1 sind es meist Wissensfragen mit 3–6 Punkten (Testarten, Testkonzept, Qualitätsmerkmale, QS-Maßnahmen). In Teil 2 gibt es immer wieder eine komplette Aufgabe mit 20–25 Punkten, die nach demselben Drehbuch abläuft: Gegeben ist eine (fehlerhafte) Methode mit Zeilennummern und eine Spezifikation → Schreibtischtest mit Testdaten → Fehler mit Zeilennummer nennen → korrigieren → Fragen zu Unit-Test und Überdeckung (S22 T2 A2, S23 T2 A3, S24 T2 A3, W25 T2 A3). Diese Punkte sind gut planbar, weil das Vorgehen immer gleich ist.

UnterthemaKategorieTypische PunkteWichtigste Fähigkeit
TQ-01 TestartenMeistens3–8 je FrageTeststufen, Black-/White-Box, Regressionstest, Testkonzept
TQ-02 Code analysieren, Fehler findenMeistens4–15Fehler mit Zeilennummer benennen und korrigieren
TQ-03 Unit-Test, ÜberdeckungsmaßeOft3–12assertEquals auswerten, C0/C1/C2, Mindestzahl Testfälle
TQ-04 Qualitätsmerkmale ISO/IEC 25010Oft4–5Merkmale beschreiben und auf ein Szenario anwenden
TQ-05 SchreibtischtestOft2–10Wertetabelle sauber und vollständig führen
TQ-06 Äquivalenzklassen, TestfälleWahrscheinlich4–10gültige/ungültige Klassen, Grenzwerte, Testfalltabelle
TQ-07 Codequalität, ReviewsWahrscheinlich5–6QS-Maßnahmen erläutern, Code-Review, Clean Code

TQ-01 · Testarten Meistens

Vorkommen: 7/9 · Prüfungen: W21, S22, W22, S23, W23, S24, W25 (fehlte nur in W24 und S26) · Teil 1 und Teil 2, meist 3–6 Punkte je Teilaufgabe

Warum testen? Grundbegriffe

Testen ist die geplante, nachvollziehbare Ausführung bzw. Prüfung eines Programms mit dem Ziel, Fehler zu finden und nachzuweisen, dass die Anforderungen erfüllt sind. Ein Test kann die Anwesenheit von Fehlern zeigen, aber nie ihre Abwesenheit beweisen (sinngemäß nach E. W. Dijkstra) – deshalb kommt es auf gut gewählte Testfälle an.

Teststufen und das V-Modell

Das V-Modell ordnet jeder Entwurfsphase (linker Ast) eine Teststufe (rechter Ast) zu. Die Testfälle einer Stufe werden aus dem Dokument derselben Ebene abgeleitet und prüfen gegen dieses Dokument.

Anforderungsdefinition (Lastenheft) Funktionaler Systementwurf (Pflichtenheft) Technischer Systementwurf (Architektur, Schnittstellen) Komponentenspezifikation (Modul-/Methodenentwurf) Implementierung Komponententest (Unit-Test, Modultest) Integrationstest (Zusammenspiel, Schnittstellen) Systemtest (Gesamtsystem, Testumgebung) Abnahmetest (durch den Auftraggeber) prüft gegen prüft gegen
Abb. A-1: V-Modell – links wird entworfen, rechts geprüft; gestrichelt: Die Teststufe prüft gegen das Ergebnis derselben Ebene
TeststufeWas wird geprüft?PrüfgrundlageWer? Wo?
Komponententest (Unit-, Modultest)einzelne Methode/Klasse isoliert; Abhängigkeiten werden durch Platzhalter (Stub, Mock) ersetztKomponentenspezifikationEntwickler, Entwicklungsumgebung, automatisiert
IntegrationstestZusammenspiel mehrerer Komponenten, Schnittstellen (z. B. App ↔ REST-API ↔ Datenbank)technischer Entwurf, SchnittstellenbeschreibungEntwickler/Tester, Integrationsumgebung
Systemtestdas vollständige System gegen alle funktionalen und nicht-funktionalen Anforderungen (Last, Sicherheit, Usability)Pflichtenheftunabhängiges Testteam, produktionsnahe Testumgebung
AbnahmetestErfüllt das System den Vertrag, ist es für den Einsatz beim Kunden geeignet? Ergebnis: Abnahmeprotokoll, ggf. FreigabeLastenheft, VertragAuftraggeber bzw. spätere Nutzer, beim Kunden

Varianten des Abnahmetests: Alpha-Test (künftige Nutzer testen beim Hersteller), Beta-Test (ausgewählte Nutzer testen in ihrer eigenen Umgebung vor der allgemeinen Freigabe).

Statisch und dynamisch, Black-Box und White-Box

Statischer TestDynamischer Test
PrinzipPrüfobjekt wird nicht ausgeführt, sondern untersuchtPrüfobjekt wird mit Testdaten ausgeführt, Ist- und Soll-Ergebnis werden verglichen
BeispieleCode-Review, Inspektion, Walkthrough, statische Codeanalyse (Linter), Schreibtischtest, Review von AnforderungsdokumentenUnit-Test, Integrations-, System-, Last-, Abnahmetest
Vorteilschon vor der Ausführbarkeit möglich, findet Fehlerursachen direkt (auch in Dokumenten)zeigt das tatsächliche Verhalten, auch Laufzeit- und Umgebungsprobleme
Black-Box-Test (funktional)White-Box-Test (strukturell, Glass-Box)
Grundlagenur die Spezifikation (Ein-/Ausgabeverhalten); der Code ist unbekannt bzw. wird nicht betrachtetder Quellcode und seine Kontrollstruktur
VerfahrenÄquivalenzklassen, Grenzwertanalyse, Entscheidungstabellen, Zustandsübergänge, AnwendungsfälleAnweisungs-, Zweig-, Pfad-, Bedingungsüberdeckung
Vorteileprüft, ob die Anforderungen erfüllt sind; findet fehlende Funktionen; Tester braucht keine Programmierkenntnisse; Testfälle früh aus der Spezifikation ableitbar; unabhängig von der Implementierungalle Programmteile werden geprüft, auch solche, die die Spezifikation nicht erfasst; Testabdeckung messbar; Fehler lassen sich genau lokalisieren; findet toten oder unnötigen Code; unterstützt die Optimierung des Codes
Nachteilekeine Aussage, welche Codeteile getestet wurden; unnötiger oder versteckter Code bleibt unentdecktfehlende Funktionen werden nicht erkannt (was nicht programmiert ist, kann nicht überdeckt werden); Codekenntnis nötig; aufwendig

Grey-Box-Test: Mischform – Testfälle aus der Spezifikation, aber mit Wissen über die innere Struktur (z. B. beim Integrationstest die Schnittstellen kennen).

Weitere Testarten

TestartZweck und Vorgehen
RegressionstestNach jeder Änderung (neue Funktion, Fehlerkorrektur, Optimierung) werden die bereits bestehenden Testfälle erneut ausgeführt, um sicherzustellen, dass die vorhandene Funktionalität nicht beeinträchtigt wurde (keine „Seiteneffekte“). Wird wegen der häufigen Wiederholung automatisiert (CI-Pipeline).
Fehlernachtest (Re-Test)prüft gezielt, ob ein gemeldeter und behobener Fehler wirklich beseitigt ist (gleicher Testfall wie bei der Fehlerentdeckung).
Smoke-Testkurzer, oberflächlicher Test der wichtigsten Grundfunktionen nach einem Build/Deployment („Startet das System, kann man sich anmelden, antwortet die Datenbank?“). Schlägt er fehl, lohnen sich weitere Tests nicht.
LasttestVerhalten unter der erwarteten (auch Spitzen-)Last: Antwortzeiten, Durchsatz, Ressourcen. Mit Lastgeneratoren werden viele gleichzeitige Benutzer simuliert (z. B. JMeter, Gatling).
StresstestLast über die Spezifikation hinaus steigern, bis das System an seine Grenzen kommt: Wo bricht es ein, verhält es sich dann kontrolliert, erholt es sich danach?
PerformancetestOberbegriff: Antwortzeiten und Ressourcenverbrauch messen (z. B. 95 % der Anfragen unter 1 s).
Usability-Testechte Nutzer der Zielgruppe lösen typische Aufgaben, man beobachtet Probleme. Methoden: Thinking Aloud (Testperson spricht ihre Gedanken laut aus), aufgabenbasierter Test mit Messung von Zeit, Fehlern und Erfolgsquote, Eye-Tracking (Blickverlauf), Fragebogen/Interview nach dem Test (z. B. SUS), A/B-Test (zwei Varianten im Vergleich), heuristische Evaluation durch Experten anhand von Regeln (z. B. DIN EN ISO 9241-110).
SicherheitstestSchwachstellen suchen, z. B. Penetrationstest (simulierter Angriff), Prüfung auf SQL-Injection, Rechteprüfung.
Kompatibilitätstestverschiedene Browser, Betriebssystemversionen, Geräte, Bildschirmgrößen.

Funktionale Tests prüfen, was das System tut (Ergebnisse). Nicht-funktionale Tests prüfen, wie gut es das tut (Last, Usability, Sicherheit, Kompatibilität) – das sind genau die Qualitätsmerkmale aus TQ-04.

Manuell oder automatisiert?

AutomatisiertManuell
Stärkenschnell, beliebig oft wiederholbar, gleiche Bedingungen, ideal für Regressionstests und CIflexibel, findet Unerwartetes (explorativ), beurteilt Bedienbarkeit und Optik
SchwächenErstellung und Pflege der Skripte kostet Zeit; prüft nur, was programmiert wurdelangsam, teuer bei Wiederholung, fehleranfällig, schlecht reproduzierbar
UI/E2E Integration Unit-Tests wenige, langsam, teuer viele, schnell, billig
Abb. A-2: Testpyramide (automatisierte Tests)

Testkonzept / Testplan

Das Testkonzept (Testplan, vgl. IEEE 829 bzw. ISO/IEC/IEEE 29119) legt vor dem Testen fest, was, wie, womit, von wem und wann getestet wird. Typische Inhalte:

Aufbau eines Testfalls (z. B. im Testprotokoll): ID · Testobjekt · Vorbedingung · Eingabe/Testschritte · erwartetes Ergebnis · tatsächliches Ergebnis · Status (bestanden/fehlgeschlagen) · Tester, Datum.

Konformität zu einer Spezifikation prüfen

Wenn ein System eine fremde, vorgegebene Spezifikation erfüllen muss (Datenformat, Norm, Schnittstelle eines Partners, z. B. die eRechnung in W25), reicht es nicht, „irgendwie“ zu testen:

Typische Falle: „Schema-valide = korrekt“Ein Schema prüft nur Struktur und Datentypen (Pflichtfelder vorhanden, Datum im richtigen Format, Zahl statt Text). Es prüft nicht die inhaltliche Richtigkeit: ob Summen stimmen, ob Werte plausibel sind, ob fachliche Regeln (Geschäftsregeln) eingehalten werden, ob die richtigen Daten des richtigen Kunden übertragen werden. Dafür braucht man zusätzlich fachliche Prüfungen (z. B. Schematron-Regeln bei XML, eigene Plausibilitätstests) und Ende-zu-Ende-Tests mit der Gegenstelle.
MerkeTeststufe = wie groß ist das Testobjekt (Komponente → Integration → System → Abnahme). Testmethode = woraus leite ich Testfälle ab (Black-Box: Spezifikation, White-Box: Code). Testart = wozu teste ich (Regression, Last, Usability, Smoke …). Diese drei Ebenen nicht verwechseln.
So wird es in der Prüfung gefragt W21 T1 A4d (4 P): Black- und White-Box-Test beschreiben. · W21 T1 A3ac (4 P): Usability-Tests beschreiben. · S24 T2 A3aa/ab (je 4 P): Vorteile des White-Box- gegenüber dem Black-Box-Test; Zweck des Regressionstests. · W23 T1 A1d (6 P): Inhalte eines Testkonzepts beschreiben – die Lösung erwartete z. B. Teststrategie, Testumgebung/Automatisierung, Zusammenspiel der Teststufen, Testplan (wer/was/wann), Aufwandsschätzung. · W25 T1 A3ba/bc (3 + 6 P): Konformität zu einer Spezifikation sicherstellen; begründen, warum eine XSD-Validierung allein nicht reicht. · Operator „beschreiben/erläutern“: nicht nur den Begriff nennen, sondern Zweck und Vorgehen in ganzen Sätzen, möglichst mit Bezug zum Szenario.

TQ-02 · Code analysieren / Fehler finden Meistens

Vorkommen: 6/9 · Prüfungen: W21 (Struktogramm checkPassword, 3 Fehler), S22 (fehlerhafte Bedingungen), W22 (rekursive Funktion), S23 (Monatsstatistik, 13 P Korrektur), S24 (Pfade notieren), W25 (fehlerhafte Minimum-Funktion) · meist Teil 2

Fehlerarten

FehlerartWann fällt er auf?Beispiele
Syntaxfehlerbeim Übersetzen (Compiler, IDE markiert rot) – Programm startet gar nichtfehlendes Semikolon oder Klammer, Schlüsselwort falsch geschrieben, nicht deklarierte Variable, Typfehler (int x = "drei";)
Laufzeitfehlerwährend der Ausführung, meist Programmabbruch mit ExceptionIndexüberschreitung (ArrayIndexOutOfBoundsException), Zugriff auf null (NullPointerException), Ganzzahldivision durch 0, Datei nicht vorhanden
Logikfehler (semantischer Fehler)gar nicht von selbst: Das Programm läuft, liefert aber falsche Ergebnisse – nur durch Tests mit bekanntem Sollergebnis oder Reviews zu findenfalsche Initialisierung, falscher Vergleichsoperator, falsche Schleifengrenze, falsche Formel, Endlosschleife, vergessener Sonderfall

Das Wort „semantisch“ (W25 T2 A3bb: „zwei semantische Fehler“) meint genau diese Logikfehler: Der Code ist syntaktisch korrekt, bedeutet aber etwas anderes, als gemeint war.

Katalog der typischen Fehler in Prüfungsaufgaben

#FehlerErkennungszeichen und Korrektur
1Falsche Initialisierungmin := 0 bzw. max := 0, obwohl alle Werte positiv bzw. auch negativ sein können → mit dem ersten Element (werte[0]) initialisieren. Zähler/Summe nicht auf 0 gesetzt oder in der falschen Schleife initialisiert (innerhalb statt außerhalb bzw. umgekehrt).
2Off-by-one bei Schleifengrenzenbis werte.length statt bis werte.length - 1 (Laufzeitfehler), Java i <= length; oder umgekehrt i < length - 1 → letztes Element fehlt; Start bei 1 statt 0 → erstes Element fehlt (nur richtig, wenn Element 0 bewusst als Startwert verwendet wurde).
3Falscher Vergleichsoperator> statt >= bei „mindestens“, „ab“; < statt <= bei „höchstens“, „bis einschließlich“; < und > vertauscht (Minimum ↔ Maximum).
4Falscher Divisor / falsche FormelDurchschnitt durch die Gesamtzahl statt durch die Anzahl der gezählten Werte; durch eine Gruppen- statt Gesamtzahl; Ganzzahldivision in Java (7 / 2 = 3) → (double) summe / anzahl; Division durch 0 bei leerer Menge nicht abgefangen.
5Letzte Gruppe / letztes Element nicht ausgewertettypisch beim Gruppenwechsel (Daten sortiert, Auswertung jeweils beim Wechsel des Gruppenbegriffs): Die letzte Gruppe erlebt keinen Wechsel mehr → nach der Schleife fehlt die Auswertung. Ebenso bei „Serien“: Die Auswertung erfolgt nur, wenn die Serie endet – endet sie mit dem letzten Element, wird sie vergessen.
6Gruppenvariablen nicht zurückgesetztbeim Gruppenwechsel werden Zähler und Summe zurückgesetzt, aber Minimum/Maximum nicht → Wert „wandert“ in die nächste Gruppe.
7Rückgabe an falscher Stellerückgabe innerhalb der Schleife → Abbruch nach dem ersten Durchlauf; Rückgabe der falschen Variable (Index statt Wert).
8Endlosschleifein einer solange-Schleife wird die Laufvariable nicht verändert oder in die falsche Richtung; Abbruchbedingung nie erreichbar.
9Logische Verknüpfung falschund statt oder; Negation falsch umgeformt (De Morgan: nicht (a und b) = nicht a oder nicht b); Klammerung.
10Sonderfall nicht behandeltnull, leeres Array/leere Liste, ein einziges Element, alle Werte gleich, negative Werte – Spezifikation genau lesen, was dann passieren soll (Exception? 0? leere Liste?).

So gehst du vor

  1. Spezifikation lesen und für die gegebenen Testdaten das erwartete Ergebnis selbst ausrechnen (ohne auf den Code zu schauen).
  2. Schreibtischtest (TQ-05) mit denselben Testdaten: Code Zeile für Zeile durchspielen, Variablenwerte notieren → tatsächliches Ergebnis.
  3. Abweichung? Die Stelle finden, an der die Werte zum ersten Mal von deiner Erwartung abweichen.
  4. Den Katalog oben durchgehen: Initialisierung, Schleifengrenzen, Vergleiche, Formel, Rückgabe, Sonderfälle, Gruppenwechsel.
  5. Jeden Fehler mit Zeilennummer, Ursache und Auswirkung benennen und die korrigierte Zeile vollständig hinschreiben (bei fehlenden Anweisungen: „nach Zeile 18 einfügen: …“).
  6. Korrektur mit den Testdaten erneut prüfen (gedanklicher Fehlernachtest) und an einen Randfall denken (leer, ein Element, negativ).

Beispiel (Wetterstation): Die Funktion soll die höchste Temperatur eines Tages liefern. Es gibt mindestens einen Messwert, Werte können negativ sein.

01 funktion hoechstwert(werte : double[]) : double
02   max : double := 0
03   zähle i von 0 bis werte.length
04     wenn werte[i] > max dann
05       max := werte[i]
06     Ende wenn
07     rückgabe max
08   Ende zähle
09 Ende funktion

Testdaten (Wintertag): [-3.5, -1.2, -4.0]

Erwartet: -1.2

Tatsächlich: 0 – im ersten Durchlauf ist -3.5 > 0 falsch, dann wird sofort max = 0 zurückgegeben.

ZeileFehler (Ursache → Auswirkung)Korrektur
02Startwert 0 ist kein Messwert → bei nur negativen Werten wird 0 geliefertmax : double := werte[0]
03Endwert werte.length ist kein gültiger Index → Laufzeitfehler im letzten Durchlaufzähle i von 1 bis werte.length - 1 (oder von 0)
07rückgabe innerhalb der Schleife → nur das erste Element wird ausgewertetZeile 07 hinter Ende zähle verschieben

Hinweis: Der Fehler in Zeile 03 fällt mit diesen Testdaten gar nicht auf, weil Zeile 07 die Schleife vorher beendet. Fehler können sich gegenseitig verdecken – nach jeder Korrektur erneut testen.

Gruppenwechsel erkennen

Viele Auswertungen (Statistik je Monat, je Filiale, je Kurs) laufen über eine nach dem Gruppenbegriff sortierte Liste. Das Muster: Gruppenbegriff des ersten Elements merken; in der Schleife bei einem Wechsel die bisherige Gruppe auswerten, Gesamtwerte fortschreiben, alle Gruppenvariablen zurücksetzen und den neuen Gruppenbegriff merken; danach das aktuelle Element verarbeiten; nach der Schleife die letzte Gruppe auswerten. Beim Prüfen eines solchen Codes gezielt fragen: Wird jede Gruppenvariable zurückgesetzt? Wird die letzte Gruppe ausgegeben? Werden die Gesamtwerte durch die richtige (Gesamt-)Anzahl geteilt? Was passiert bei leerer Liste (Zugriff auf das erste Element)?

Typische Fehler beim Antworten Nur das Symptom nennen („Ergebnis ist falsch“) statt Zeile + Ursache. · Die ganze Funktion neu schreiben, obwohl „Korrigieren Sie die fehlerhaften Zeilen“ gefragt ist (kostet Zeit, und neue Fehler kosten Punkte). · Einen Fehler „finden“, der keiner ist (z. B. zähle i von 1, wenn vorher max := werte[0] gesetzt wurde – das ist korrekt). · Java-Ganzzahldivision übersehen. · Bei „Nennen Sie zwei Fehler“ denselben Fehler zweimal in anderen Worten nennen.
So wird es in der Prüfung gefragt S23 T2 A3a (15 P): Statistik je Monat und Jahr (Gruppenwechsel) mit Datenverlaufstabelle prüfen, zwei Fehler nennen (2 P), Änderungen/Erweiterungen angeben, sodass die vorgegebene Ausgabe entsteht (13 P) – Fehler waren u. a. die nicht ausgegebene letzte Gruppe und ein falscher Divisor. · W25 T2 A3b (14 P): Minimum-Funktion mit Exception für null/leer: erwartetes und tatsächliches Ergebnis für fünf Testdaten eintragen, dann zwei semantische Fehler (Startwert 0, Schleifengrenze length-1) korrigieren. · S22 T2 A2bb (4 P): fehlerhafte Bedingungen so anpassen, dass der Unit-Test erfolgreich ist. · W21 T2 A1c (6 P): drei Fehler in einem Struktogramm zur Passwortprüfung finden.

TQ-03 · Unit-Test / Überdeckungsmaße Oft

Vorkommen: 5/9 · Prüfungen: S22, W22, S23, S24, W25 · fast immer Teil 2, oft als Teil einer 20–25-Punkte-Testaufgabe

Was ist ein Unit-Test?

Ein Unit-Test (Komponenten-, Modultest) ist ein automatisierter Test der kleinsten testbaren Einheit eines Programms – meist einer Methode oder Klasse – isoliert vom Rest des Systems. Er ruft die Einheit mit festgelegten Eingaben auf und vergleicht das tatsächliche mit dem erwarteten Ergebnis. Unit-Tests werden von den Entwicklern selbst geschrieben, meist mit einem Framework (Java: JUnit, C#: NUnit/xUnit, Python: unittest/pytest).

Wozu? Fehler früh und genau lokalisiert finden (man weiß, welche Methode fehlschlägt) · bei jeder Änderung automatisch erneut ausführen (Regressionstest, z. B. in der CI-Pipeline) · Absicherung beim Refactoring · ausführbare Dokumentation, wie eine Methode benutzt wird · zwingt zu testbarem, lose gekoppeltem Design.

Eigenschaft (FIRST)Bedeutung
Fast – schnellläuft in Millisekunden, damit man tausende Tests bei jeder Änderung ausführen kann
Independent/Isolated – unabhängighängt nicht von anderen Tests, ihrer Reihenfolge, einer echten Datenbank, dem Netz oder der Uhrzeit ab; Abhängigkeiten werden durch Stubs/Mocks ersetzt
Repeatable – wiederholbarliefert bei jeder Ausführung und auf jedem Rechner dasselbe Ergebnis (deterministisch)
Self-validating – selbstprüfendentscheidet selbst über bestanden/fehlgeschlagen (Assertion), niemand muss Ausgaben ansehen
Timely – zeitnahwird zusammen mit (oder vor) dem Code geschrieben, nicht Wochen später

Weitere Merkmale guter Unit-Tests: ein Test prüft genau einen Sachverhalt (aussagekräftiger Name wie leererWarenkorbKostetNichts), lesbar, wartbar, deckt Normal-, Grenz- und Fehlerfälle ab.

Stub = Platzhalter, der feste Antworten liefert (z. B. statt der Datenbank immer drei Testkunden). Mock = Platzhalter, der zusätzlich prüft, ob und wie er aufgerufen wurde. Testtreiber = Code, der die zu testende Einheit aufruft (bei JUnit: die Testklasse).

Aufbau: Arrange – Act – Assert

Jede Testmethode folgt demselben Dreischritt: Arrange (Vorbereiten: Objekte anlegen, Ausgangszustand und Testdaten herstellen) → Act (Ausführen: genau die zu testende Methode aufrufen) → Assert (Prüfen: tatsächliches mit erwartetem Ergebnis vergleichen). Beispiel aus einem Bank-Szenario:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class KontoTest {

    @Test
    void einzahlungErhoehtKontostand() {
        Konto konto = new Konto(100.00);                  // Arrange
        konto.einzahlen(50.00);                           // Act
        assertEquals(150.00, konto.getStand(), 0.001);    // Assert (Delta bei double)
    }

    @Test
    void negativeAbhebungWirdAbgelehnt() {
        Konto konto = new Konto(100.00);                  // Arrange
        assertThrows(IllegalArgumentException.class,      // Act + Assert:
                     () -> konto.abheben(-20.00));        // erwartete Exception
    }
}
JUnit 5 (Auszug)Bedeutung
@Testmarkiert eine Testmethode
@BeforeEachMethode läuft vor jedem Test (gemeinsames Arrange, z. B. Objekt neu anlegen)
assertEquals(expected, actual)bestanden, wenn erwarteter und tatsächlicher Wert gleich sind – Reihenfolge: erst erwartet, dann tatsächlich
assertEquals(expected, actual, delta)für double: gleich bis auf die Toleranz delta (Rundungsfehler bei Kommazahlen)
assertTrue(b), assertFalse(b), assertNull(o)Bedingung wahr/falsch, Objekt null
assertThrows(Typ.class, () -> aufruf)bestanden, wenn der Aufruf eine Exception dieses Typs (oder einer Unterklasse) wirft; wird keine oder eine andere Exception geworfen, schlägt der Test fehl
assertAll(() -> …, () -> …)führt alle Prüfungen aus und meldet alle Fehlschläge gemeinsam
@ParameterizedTest + @CsvSource({"20, 15, 5", …})eine Testmethode, mehrfach mit verschiedenen Datenzeilen ausgeführt – jede Zeile erscheint als eigener Testfall
Merke: assertEquals auswertenFür jeden Testfall den Methodenaufruf mit dem gegebenen (ggf. fehlerhaften) Code selbst ausrechnen → tatsächlicher Wert. Stimmt er mit dem ersten Parameter (expected) überein: OK, sonst Fehler. Wichtig für die Praxis: Eine JUnit-Testmethode bricht beim ersten fehlgeschlagenen assert ab; die folgenden asserts derselben Methode werden nicht mehr ausgeführt. In Prüfungstabellen (S22) wird trotzdem jede Zeile einzeln bewertet – das ist dort ausdrücklich so gemeint.

Test-Driven Development (TDD)

1 · Red Test schreiben, der fehlschlägt 2 · Green gerade so viel Code, dass der Test besteht 3 · Refactor Code aufräumen, Tests bleiben grün nächste kleine Anforderung
Abb. A-3: TDD-Zyklus „Red – Green – Refactor“: Der Test entsteht vor dem Produktivcode

Vorteile: jede Zeile Code ist durch einen Test begründet (hohe Abdeckung), Anforderungen werden vorab präzisiert, kleine Schritte, sicheres Refactoring. Nachteile: anfangs mehr Aufwand, Disziplin nötig, bei unklaren Anforderungen oder GUI-lastigem Code schwierig.

Kontrollflussgraph

White-Box-Überdeckungsmaße werden am Kontrollflussgraphen erklärt: Knoten = Anweisungen bzw. Bedingungen (oft mit Zeilennummer beschriftet), Kanten = mögliche Übergänge. Eine Bedingung hat zwei ausgehende Kanten (wahr/falsch) – auch ein wenn ohne sonst: Seine falsch-Kante führt direkt hinter das Ende wenn.

01 funktion versandkosten(gewicht : double,
         express : boolean) : double
02   kosten : double := 4.90
03   wenn gewicht > 10 dann
04     kosten := kosten + 6.00
05   Ende wenn
06   wenn express dann
07     kosten := kosten + 8.00
08   Ende wenn
09   rückgabe kosten
10 Ende funktion
02 03 04 06 07 09 wahr falsch wahr falsch Pfade: P1: 2-3-4-6-7-9 P2: 2-3-4-6-9 P3: 2-3-6-7-9 P4: 2-3-6-9
Abb. A-4: Kontrollflussgraph zu versandkosten

Die drei Überdeckungsmaße

MaßForderungBeispiel versandkosten
Anweisungsüberdeckung
(C0, statement coverage)
Jede Anweisung wird mindestens einmal ausgeführt. Maß: ausgeführte Anweisungen ÷ alle Anweisungen · 100 %.1 Testfall genügt: gewicht = 12, express = wahr (Pfad P1 führt alle Anweisungen aus)
Zweigüberdeckung
(C1, branch/decision coverage)
Jeder Zweig (jede Kante, jedes Ergebnis wahr und falsch jeder Bedingung) wird mindestens einmal durchlaufen. Schließt C0 ein.2 Testfälle: (12, wahr) und (5, falsch) – die falsch-Kanten 03→06 und 06→09 fehlen sonst
Pfadüberdeckung
(C2, path coverage)
Jeder mögliche Pfad vom Eintritt bis zum Austritt wird mindestens einmal durchlaufen. Schließt C1 und C0 ein.4 Testfälle: (12, wahr), (12, falsch), (5, wahr), (5, falsch)
Pfadüberdeckung (C2) – stärkstes Maß, meist sehr viele Testfälle Zweigüberdeckung (C1) – in der Praxis üblicher Mindeststandard Anweisungsüberdeckung (C0) schwächstes Maß, findet z. B. nicht ausführbaren („toten“) Code
Abb. A-5: 100 % C2 ⇒ 100 % C1 ⇒ 100 % C0 – die Umkehrung gilt nicht

Ergänzend gibt es die Bedingungsüberdeckung (condition coverage): Bei zusammengesetzten Bedingungen wie a > 0 und b > 0 muss jede Teilbedingung einmal wahr und einmal falsch werden (Mehrfachbedingungsüberdeckung: alle Kombinationen). Achtung Bezeichnung: In deutschen Lehrbüchern steht C2 meist für Pfad-, C3 für Bedingungsüberdeckung; manche englischen Quellen nummerieren anders. In der Prüfung werden die Begriffe ausgeschrieben.

So bestimmst du die Mindestanzahl der Testfälle

  1. Kontrollflussgraph skizzieren oder im Code jede Bedingung (B1, B2 …) und jede Anweisung im Zweig (A1, A2 …) markieren – so macht es auch die IHK (S24 T2 A3c).
  2. C0: Welche Anweisungen schließen sich gegenseitig aus (z. B. dann- und sonst-Teil derselben Bedingung, oder ein Zweig, in dem man früh mit rückgabe/Exception aussteigt)? Mindestens so viele Testfälle wie sich gegenseitig ausschließende Anweisungsgruppen; dann so kombinieren, dass jeder Testfall möglichst viele Anweisungen mitnimmt.
  3. C1: Zusätzlich muss jede Bedingung auch ihren „leeren“ falsch-Zweig nehmen. Gezielt prüfen, ob die bisherigen Testfälle jede Bedingung einmal wahr und einmal falsch machen.
  4. C2: Pfade zählen. Faustregel ohne Schleifen: nacheinander stehende, unabhängige Verzweigungen → Pfadzahlen multiplizieren (2 · 2 = 4); alternative Zweige (dann/sonst, verschachtelt) → Pfadzahlen der Zweige addieren. Danach die Pfade einzeln aufschreiben und zählen.
  5. Testdaten angeben, die genau diesen Pfad erzwingen, und prüfen, ob der Pfad überhaupt möglich ist (manche Kombinationen sind logisch unmöglich).

Schleifen: Jede weitere Wiederholung erzeugt einen neuen Pfad – vollständige Pfadüberdeckung ist dann praktisch unmöglich. Man begrenzt sich z. B. auf Schleife 0-mal, 1-mal und mehrmals durchlaufen (Boundary-Interior-Test). Für C0 und C1 reicht oft ein Testfall, der die Schleife mehrmals durchläuft, plus einer, der sie nicht betritt.

Englische Begriffe (kommen im Fachtext vor, S24): statement coverage, branch coverage / decision coverage, path coverage, condition coverage, test case, test suite, assertion, expected/actual result, coverage tool, executed / not executed.

Typische Fallen 100 % Überdeckung heißt nicht fehlerfrei: Überdeckung misst nur, welcher Code ausgeführt wurde – nicht, ob das Ergebnis mit einer sinnvollen Assertion geprüft wurde, und schon gar nicht, ob Funktionalität fehlt (fehlender Code kann nicht „nicht überdeckt“ sein). Der Minimum-Fehler „Startwert 0“ wird mit voller Anweisungsüberdeckung oft nicht gefunden. · Bei der Mindestanzahl für C0 die „leere“ falsch-Kante vergessen ist richtig (C0 braucht sie nicht), bei C1 ein Fehler. · Bei C2 Pfade vergessen, die ohne sonst entstehen. · „Mindestanzahl“ immer mit kurzer Begründung bzw. konkreten Testdaten angeben.
So wird es in der Prüfung gefragt S22 T2 A2a (7 P): Unit-Test beschreiben (3 P) und zwei Eigenschaften nennen und beschreiben (4 P); A2ba (5 P): fünf assertEquals-Zeilen mit OK/Fehler auswerten. · W25 T2 A3a (6 P): Unit-Test beschreiben, Testabdeckung bezogen auf Anweisungen erläutern. · W22 T2 A2ac (3 P), S23 T2 A3b (10 P): Anweisungsüberdeckung erläutern, Mindestzahl Testfälle, nicht durchlaufene Anweisungen nennen, Testdaten für volle Überdeckung anpassen. · S24 T2 A3b/c (12 + 5 P): Anweisungs-, Zweig- und Pfadüberdeckung anhand eines englischen Fachtextes erläutern (je 4 P) und alle Pfade eines Login-Algorithmus in der Notation „B1, A1, B2, …“ notieren.

TQ-04 · Qualitätsmerkmale ISO/IEC 25010 Oft

Vorkommen: 4/9 · Prüfungen: W21 (Effizienz und Änderbarkeit), S23 (Qualitätsmerkmale nach ISO 9126!), S24 (Qualität/QS-Maßnahmen), S26 (Zuverlässigkeit + weiteres Merkmal) · Teil 1, 4–5 Punkte

Die Norm ISO/IEC 25010 („SQuaRE“, Nachfolger der ISO/IEC 9126) beschreibt ein Produktqualitätsmodell: Software-Qualität wird in Merkmale und Untermerkmale zerlegt, damit man sie beschreiben, als nicht-funktionale Anforderung festlegen und prüfen kann. Die Fassung von 2011 hat 8 Merkmale:

MerkmalUntermerkmaleLeitfrageBeispiel (Online-Banking-App)
Funktionale Eignung (functional suitability)funktionale Vollständigkeit, Korrektheit, AngemessenheitTut die Software das Richtige, vollständig und richtig?Überweisungen werden mit korrektem Betrag ausgeführt; alle im Lastenheft geforderten Funktionen sind vorhanden.
Leistungseffizienz (performance efficiency)Zeitverhalten, Ressourcennutzung (Verbrauchsverhalten), KapazitätWie schnell und sparsam?Kontostand erscheint in < 2 s; die App braucht < 150 MB Speicher; 20 000 gleichzeitige Nutzer.
Kompatibilität (compatibility)Koexistenz, InteroperabilitätArbeitet sie mit anderen Systemen zusammen?Datenaustausch mit dem Kernbankensystem über eine Standardschnittstelle; läuft neben anderen Apps ohne Störung.
Benutzbarkeit (usability)Erkennbarkeit der Eignung, Erlernbarkeit, Bedienbarkeit, Schutz vor Fehlbedienung, Ästhetik der Oberfläche, Zugänglichkeit (Barrierefreiheit)Können die Nutzer sie leicht, effektiv und zufrieden nutzen?Sicherheitsabfrage vor dem Löschen einer Vorlage; Bedienung mit Screenreader möglich.
Zuverlässigkeit (reliability)Reife, Verfügbarkeit, Fehlertoleranz, WiederherstellbarkeitFunktioniert sie dauerhaft und auch bei Störungen?Verfügbarkeit 99,9 %; bei Verbindungsabbruch wird keine Überweisung doppelt ausgeführt; nach Absturz in 15 min wieder verfügbar.
Sicherheit (security)Vertraulichkeit, Integrität, Nichtabstreitbarkeit, Verantwortlichkeit (Zurechenbarkeit), AuthentizitätSind Daten und Funktionen vor unbefugtem Zugriff geschützt?Zwei-Faktor-Anmeldung; verschlüsselte Übertragung; jede Transaktion ist einem Nutzer zugeordnet und protokolliert.
Wartbarkeit (maintainability)Modularität, Wiederverwendbarkeit, Analysierbarkeit, Modifizierbarkeit (Änderbarkeit), Testbarkeit (Prüfbarkeit)Wie leicht lässt sie sich ändern, korrigieren, erweitern?Neue Zahlungsart als eigenes Modul ergänzbar; Fehlerursachen über Logdateien schnell auffindbar.
Übertragbarkeit (portability)Anpassbarkeit, Installierbarkeit, AustauschbarkeitLässt sie sich in eine andere Umgebung bringen?läuft auf Android und iOS, verschiedenen Bildschirmgrößen; Update ohne Datenverlust installierbar.

Neben dem Produktqualitätsmodell definiert die Norm die Nutzungsqualität (quality in use): Effektivität, Effizienz, Zufriedenheit, Freiheit von Risiken, Kontextabdeckung – also die Qualität, die der Nutzer im tatsächlichen Einsatz erlebt.

Ältere Norm ISO/IEC 9126 und Neufassung 2023

ISO/IEC 9126 (6 Merkmale)Untermerkmale 9126wird in ISO/IEC 25010 (2011) zu …
FunktionalitätAngemessenheit, Richtigkeit, Interoperabilität, Sicherheit, OrdnungsmäßigkeitFunktionale Eignung; Sicherheit wird eigenes Merkmal; Interoperabilität wandert zur neuen Kompatibilität
ZuverlässigkeitReife, Fehlertoleranz, WiederherstellbarkeitZuverlässigkeit (+ Verfügbarkeit)
BenutzbarkeitVerständlichkeit, Erlernbarkeit, Bedienbarkeit, AttraktivitätBenutzbarkeit (+ Schutz vor Fehlbedienung, Zugänglichkeit)
EffizienzZeitverhalten, VerbrauchsverhaltenLeistungseffizienz (+ Kapazität)
ÄnderbarkeitAnalysierbarkeit, Modifizierbarkeit, Stabilität, PrüfbarkeitWartbarkeit (+ Modularität, Wiederverwendbarkeit)
ÜbertragbarkeitAnpassbarkeit, Installierbarkeit, Koexistenz, AustauschbarkeitÜbertragbarkeit; Koexistenz wandert zur Kompatibilität

Jedes 9126-Merkmal hat zusätzlich das Untermerkmal „Konformität“ (Einhaltung von Normen). Neu als eigene Hauptmerkmale in 25010: Sicherheit und Kompatibilität.

ISO/IEC 25010:2023 erweitert auf 9 Merkmale: Benutzbarkeit heißt nun Interaktionsfähigkeit (interaction capability, u. a. mit Inklusivität und Selbstbeschreibungsfähigkeit), Übertragbarkeit heißt Flexibilität (neu mit Skalierbarkeit), Reife heißt Fehlerfreiheit (faultlessness), Sicherheit erhält „Widerstandsfähigkeit“ (resistance), und neu ist Safety (Betriebssicherheit: Schutz von Menschen und Umwelt, z. B. sicherer Zustand bei Ausfall, Gefahrenwarnung). Die bisherigen Prüfungen haben die Begriffe der Fassung 2011 (bzw. sogar der ISO 9126) verwendet – lerne diese sicher und kenne die Umbenennungen.

Qualitätsanforderungen messbar machen

„Die App soll schnell und zuverlässig sein“ ist nicht prüfbar. Eine Qualitätsanforderung braucht eine Messgröße, einen Zielwert und Messbedingungen:

MerkmalMessgrößemessbare Formulierung (Beispiel Online-Banking)
LeistungseffizienzAntwortzeit (Perzentil), Durchsatz, Speicher-/CPU-Bedarf„Bei 5 000 gleichzeitigen Nutzern werden 95 % der Kontoabfragen in höchstens 2 s beantwortet.“
ZuverlässigkeitVerfügbarkeit in %, MTBF (mittlere Zeit zwischen Ausfällen), MTTR (mittlere Reparaturzeit), Wiederherstellungszeit„Verfügbarkeit mindestens 99,9 % pro Monat (= höchstens 43,2 min Ausfall bei 30 Tagen); nach einem Serverausfall ist der Dienst in höchstens 15 min wiederhergestellt.“
BenutzbarkeitZeit/Fehlerquote/Erfolgsquote bei Aufgaben, Zufriedenheitswert (Fragebogen)„8 von 10 Erstnutzern führen ohne Hilfe eine Überweisung in höchstens 3 Minuten aus.“
WartbarkeitZweigüberdeckung der Unit-Tests, zyklomatische Komplexität je Methode, Aufwand für Änderungen„Zweigüberdeckung mindestens 80 %; keine Methode mit Komplexität über 10.“
SicherheitBefunde im Penetrationstest, Verschlüsselungsstandard, Sperrregeln„Nach 3 falschen PIN-Eingaben wird der Zugang 30 min gesperrt; keine kritischen Befunde im Penetrationstest.“
Übertragbarkeitunterstützte Plattformen/Versionen, Installationsdauer„Lauffähig auf Android ab Version 12 und iOS ab Version 16.“

Verfügbarkeit = MTBF ÷ (MTBF + MTTR). Rechenbeispiel: 99,5 % pro Monat mit 30 Tagen erlaubt 0,5 % · 30 · 24 h = 3,6 h Ausfall.

Zielkonflikte zwischen Merkmalen sind typisch und müssen abgewogen werden: Sicherheit ↔ Benutzbarkeit (Zwei-Faktor-Anmeldung ist sicherer, aber umständlicher), Leistungseffizienz ↔ Wartbarkeit (hoch optimierter Code ist schwerer verständlich), Übertragbarkeit ↔ Leistung (plattformübergreifendes Framework statt nativer App), Sicherheit ↔ Leistung (Verschlüsselung kostet Rechenzeit).

Typische Fallen „Sicherheit“ in 25010 meint Informationssicherheit (security), nicht Betriebssicherheit/Unfallschutz (safety – erst in der Fassung 2023). · Funktionale Anforderungen („Das System soll Rechnungen erstellen“) sind kein Qualitätsmerkmal – die Merkmale beschreiben, wie gut etwas funktioniert. · Beim „Beschreiben“ nicht nur den Namen nennen, sondern die Bedeutung erklären und ein konkretes Beispiel aus dem Szenario geben. · Zuverlässigkeit (funktioniert dauerhaft) nicht mit funktionaler Korrektheit (rechnet richtig) verwechseln.
So wird es in der Prüfung gefragt W21 T1 A4ca (4 P): die Qualitätsmerkmale Effizienz und Änderbarkeit beschreiben. · S23 T1 A2a (4 P): Qualitätsmerkmale nach ISO 9126 nennen bzw. beschreiben – deshalb die alten Begriffe kennen. · S26 T1 A4a (5 P): Zuverlässigkeit erläutern und ein weiteres Merkmal mit Beispiel aus dem Szenario. · Erwartet wird jeweils: Begriff + Bedeutung + Bezug zur Situation (z. B. Sensoren auf dem Feld, Fahrplan-App).

TQ-05 · Schreibtischtest Oft

Vorkommen: 4/9 · Prüfungen: S22 (assertEquals-Fälle durchrechnen), W22 (rekursive Umwandlung Dezimal → Binär), S23 (Datenverlaufstabelle zur Monatsstatistik), W25 (erwartetes und tatsächliches Ergebnis für fünf Testdaten, 10 P) · Teil 2

Beim Schreibtischtest (Trockentest, „dry run“) spielt man einen Algorithmus von Hand ohne Computer mit konkreten Testdaten durch und notiert nach jedem Schritt die Werte aller Variablen in einer Tabelle. Weil das Programm dabei nicht ausgeführt wird, zählt er zu den statischen Prüfverfahren. Er dient dazu, die Arbeitsweise zu verstehen, das tatsächliche Ergebnis zu ermitteln und so Logikfehler zu finden.

Drei Tabellenformen, die in Prüfungen vorkommen

  1. Trace-Tabelle (am häufigsten): eine Spalte je Variable bzw. Bedingung, eine Zeile je Schritt oder Schleifendurchlauf.
  2. Datenverlaufstabelle (S23): eine Zeile je Variable, in der Spalte „Werteverlauf“ alle Werte nacheinander, durch Kommas getrennt.
  3. Testtabelle (W25): je Zeile ein Satz Testdaten mit erwartetem (aus der Spezifikation) und tatsächlichem Ergebnis (aus dem Code).

So gehst du vor

  1. Alle Variablen (auch Laufvariablen) als Spalten anlegen; bei Bedarf eine Spalte für das Ergebnis jeder Bedingung (wahr/falsch).
  2. Erste Zeile: Anfangswerte nach der Initialisierung.
  3. Den Code Zeile für Zeile ausführen – nicht „im Kopf abkürzen“. Bei jeder Zuweisung den neuen Wert eintragen; unveränderte Werte darf man in der Trace-Tabelle wiederholen oder leer lassen (Hauptsache eindeutig).
  4. Schleifen: Bedingung vor jedem Durchlauf prüfen (bei zähle: ist der Endwert erreicht?). Die Laufvariable ändert sich erst am Ende des Durchlaufs.
  5. Integer-Rechnung beachten (7 div 2 = 3, 7 mod 2 = 1, in Java 7 / 2 = 3).
  6. Am Ende Rückgabewert/Ausgabe angeben und mit dem erwarteten Ergebnis vergleichen.

Beispiel Schleife – Anzahl der Anstiege in einer Messreihe:

01 funktion zaehleAnstiege(werte : integer[]) : integer
02   anzahl : integer := 0
03   zähle i von 1 bis werte.length - 1
04     wenn werte[i] > werte[i - 1] dann
05       anzahl := anzahl + 1
06     Ende wenn
07   Ende zähle
08   rückgabe anzahl
09 Ende funktion
Trace für werte = [3, 5, 5, 8, 2, 4]
iwerte[i-1]werte[i]Z. 04anzahl
––––0
135wahr1
255falsch1
358wahr2
482falsch2
524wahr3

Rückgabe: 3. Dieselbe Rechnung als Datenverlaufstabelle:

TypVariableWerteverlauf
integeri1, 2, 3, 4, 5
integeranzahl0, 1, 2, 3

Beispiel verschachtelte Schleifen: Die innere Schleife läuft bei jedem Durchlauf der äußeren vollständig ab. Variablen, die in der äußeren Schleife initialisiert werden, beginnen bei jedem äußeren Durchlauf neu.

01 summe : integer := 0
02 zähle i von 0 bis 2
03   zähle j von i bis 2
04     summe := summe + j
05   Ende zähle
06 Ende zähle
ijsumme
000
011
023
114
126
228

Beispiel Rekursion: eine Zeile je Aufruf; erst alle Aufrufe nach unten bis zum Basisfall notieren, dann die Rückgabewerte von unten nach oben einsetzen. Euklidischer Algorithmus ggT(a, b): wenn b = 0 dann rückgabe a sonst rückgabe ggT(b, a mod b).

Aufrufabb = 0?a mod bRückgabe
18436nein12Ergebnis von Aufruf 2 = 12
23612nein0Ergebnis von Aufruf 3 = 12
3120ja (Basisfall)–12
Typische Fehler Werte nur am Ende statt nach jeder Zuweisung notieren (dann sieht man nicht, wo es schiefgeht). · Den Code so durchspielen, wie er gemeint ist, statt wie er dasteht – im Schreibtischtest wird der gegebene, ggf. fehlerhafte Code exakt befolgt. · Laufvariable einen Durchlauf zu weit oder zu kurz führen. · Bei verschachtelten Schleifen vergessen, dass die Initialisierung vor der inneren Schleife bei jedem äußeren Durchlauf erneut ausgeführt wird (oder eben gerade nicht, wenn sie außerhalb steht). · Kurzschlussauswertung übersehen: Bei a oder b wird b nicht mehr ausgewertet, wenn a schon wahr ist (so schützt z. B. i >= n oder werte[i] = 0 vor einem Indexfehler).
So wird es in der Prüfung gefragt S23 T2 A3a: Den Code mit vorgegebenen Testdaten überprüfen und dazu eine Datenverlaufstabelle ausfüllen – vorgegeben waren Typ und Variablenname, einzutragen der Werteverlauf. · W25 T2 A3ba (10 P): Tabelle mit fünf Testdaten (darunter negative Werte, ein Element, null) – je erwartetes und tatsächliches Ergebnis. · W22 T2 A2aa (4 P): rekursive Funktion mit einem Startwert durchspielen. · S22 T2 A2ba (5 P): für jede assertEquals-Zeile den Rückgabewert ausrechnen.

TQ-06 · Äquivalenzklassen / Testfälle Wahrscheinlich

Vorkommen: 3/9 · Prüfungen: S22 (Testdaten aus zwei weiteren Äquivalenzklassen), S23 (Testdaten für volle Anweisungsüberdeckung anpassen), W25 (Testdaten mit Sonderfällen) · Teil 2, 4–10 Punkte

Alle möglichen Eingaben zu testen ist unmöglich (schon ein int-Parameter hat über 4 Milliarden Werte). Man braucht deshalb wenige, aber gut gewählte Testfälle. Die beiden wichtigsten Black-Box-Verfahren:

Äquivalenzklassenbildung

Der Wertebereich jeder Eingabe wird in Äquivalenzklassen (ÄK) zerlegt: Mengen von Werten, für die sich das Programm laut Spezifikation gleich verhält. Man nimmt an: Findet ein Wert der Klasse einen Fehler, finden ihn alle; findet einer keinen, findet ihn keiner. Deshalb genügt ein Repräsentant je Klasse.

Merke: Testfälle aus Äquivalenzklassen zusammenstellenGültige Klassen verschiedener Parameter dürfen in einem Testfall kombiniert werden (so wenige Testfälle wie möglich, bis jede gültige Klasse einmal vorkam). Ungültige Klassen werden einzeln getestet, jeweils kombiniert mit gültigen Werten für alle anderen Parameter – sonst verdeckt die erste Fehlermeldung den zweiten Fehler (Fehlermaskierung) und man weiß nicht, welche Prüfung gegriffen hat.

Grenzwertanalyse

Fehler sitzen besonders oft an den Rändern der Klassen (< statt <=, Off-by-one). Deshalb testet man zusätzlich die Grenzwerte: den Wert genau auf der Grenze und den direkt benachbarten Wert auf der anderen Seite (bei Ganzzahlen ±1, bei Beträgen ±0,01). Für den Bereich 1–99: 0, 1, 99, 100 (strenge Variante zusätzlich 2 und 98).

Beispiel: Notenschlüssel – eine Funktion note(punkte : integer) : integer rechnet 0–100 Punkte in eine Note um (1: 92–100, 2: 81–91, 3: 67–80, 4: 50–66, 5: 30–49, 6: 0–29), sonst Fehlermeldung.

ungültig gültige Äquivalenzklassen (je Note eine) ungültig < 0 Note 6 5 4 3 2 1 > 100 0 – 29 30 – 49 50 – 66 67 – 80 81 – 91 92 – 100 Grenzwertpaare: −1/0 · 29/30 · 49/50 · 66/67 · 80/81 · 91/92 · 100/101
Abb. A-6: Äquivalenzklassen und Grenzwerte des Notenschlüssels
Nr.ÄquivalenzklasseRepräsentanterwartetes Ergebnis
ÄK1gültig: 92–100951
ÄK2 … ÄK6gültig: 81–91, 67–80, 50–66, 30–49, 0–2985, 70, 60, 40, 102, 3, 4, 5, 6
ÄK7ungültig: < 0−5Fehlermeldung
ÄK8ungültig: > 100120Fehlermeldung
ÄK9ungültig: keine ganze Zahl (Text, leer)„abc“Fehlermeldung (bei Eingabe über ein Textfeld)

Ergebnis: 9 Testfälle aus Äquivalenzklassen plus 14 Grenzwerte (einige fallen zusammen, z. B. 0 und 100 sind gleichzeitig Repräsentanten).

Mehrere Parameter – Beispiel Online-Shop versandpreis(gewichtKg : double, land : string): Gewicht > 0 bis 31,5 kg in drei Preisstufen (bis 2 kg, bis 10 kg, darüber), Land ∈ {„DE“, „AT“, „CH“}. Testfalltabelle nach der Regel „gültige kombinieren, ungültige einzeln“:

Nr.gewichtKglandabgedeckte Klassenerwartet
11,5„DE“Gewicht Stufe 1, DEPreis Stufe 1 DE
25,0„AT“Gewicht Stufe 2, ATPreis Stufe 2 AT
320,0„CH“Gewicht Stufe 3, CHPreis Stufe 3 CH
40,0„DE“ungültig: Gewicht ≤ 0Fehler
540,0„DE“ungültig: Gewicht > 31,5Fehler
65,0„FR“ungültig: anderes LandFehler
75,0nullungültig: Land fehltFehler

Weitere Hinweise zur Testfallauswahl

Typische Fehler Nur gültige Klassen bilden. · Zwei ungültige Werte in einem Testfall kombinieren. · Für jede gültige Klasse jedes Parameters einen eigenen Testfall anlegen, obwohl nach „möglichst wenigen“ gefragt ist. · Grenzwerte nur auf einer Seite der Grenze testen. · Erwartetes Ergebnis weglassen. · „Zahl außerhalb“ als nur eine ungültige Klasse statt zwei (zu klein / zu groß).
So wird es in der Prüfung gefragt S22 T2 A2bc (4 P): Weil im Unit-Test noch Testfälle fehlen, sollen Testdaten aus zwei weiteren Äquivalenzklassen angegeben werden, für die die Methode −1 liefern muss – also ungültige Klassen, die die vorhandenen Testfälle noch nicht abdecken. · S23 T2 A3bc (4 P): Testdaten so anpassen, dass alle Anweisungen durchlaufen werden, und die Änderungen begründen. · W25 T2 A3ba: Testdaten mit Sonderfällen (negative Zahlen, ein Element, null) auswerten.

TQ-07 · Codequalität / Reviews Wahrscheinlich

Vorkommen: 2/9 · Prüfungen: W21 (Dokumentation einer Bibliothekserweiterung; Bewertung „nur automatische Code-Reviews und Unit-Tests“), S24 (drei qualitätssichernde Maßnahmen) · dazu S23 T1 A1e (QS-Maßnahmen) · Teil 1, 4–6 Punkte

Qualitätssicherung im Entwicklungsprozess

Konstruktive QS (Fehler vermeiden)Analytische QS (Fehler finden)
IdeeRahmenbedingungen so setzen, dass Fehler gar nicht erst entstehenvorhandene Ergebnisse prüfen und bewerten
Beispieledefiniertes Vorgehensmodell (z. B. Scrum mit Definition of Done), Coding-Richtlinien und Namenskonventionen, Entwurfsmuster und Architekturvorgaben, geeignete Werkzeuge (IDE, Versionsverwaltung, CI/CD-Pipeline), Vorlagen und Verfahrensanweisungen zur Dokumentation, Schulung/Zertifizierung der Entwickler und Tester, Pair Programming, TDDCode-Reviews und Inspektionen, statische Codeanalyse, Tests aller Stufen (Unit bis Abnahme) mit standardisierten Testumgebungen, -verfahren und -daten, Messung von Metriken (Testabdeckung, Komplexität), Audits

Für die Prüfung gilt: Eine Maßnahme erläutern heißt, sie zu benennen und zu beschreiben, wie sie die Qualität verbessert (z. B. „Code-Reviews: Jede Änderung wird vor dem Zusammenführen von einem zweiten Entwickler geprüft; so werden Logikfehler und Verstöße gegen Richtlinien früh gefunden und das Wissen im Team verteilt“).

Code-Review

Beim Code-Review lesen und bewerten andere Entwickler den Code, bevor er übernommen wird (Vier-Augen-Prinzip). Heute meist als Pull-Request-/Merge-Request-Review im Git-Workflow.

ReviewartMerkmale (vom informellsten zum formalsten)
Informelles ReviewKollege schaut drüber („Schulterblick“), keine Dokumentation
WalkthroughAutor stellt den Code vor und führt durch, Teilnehmer stellen Fragen; dient auch dem Wissenstransfer
Technisches ReviewFachleute prüfen gegen Vorgaben/Checkliste, Ergebnisse werden protokolliert, Entscheidung über Freigabe
Inspektionformalstes Verfahren mit Rollen (Moderator, Autor, Gutachter, Protokollant), Checklisten, Metriken und Nachkontrolle
1 · Planung Umfang, Reviewer und Checkliste festlegen 2 · Vorbereitung Reviewer prüfen den Code einzeln (mit Checkliste) 3 · Review Befunde besprechen bzw. als Kommentar im Pull-Request 4 · Nacharbeit Autor behebt die Befunde und lädt Änderung hoch 5 · Abschluss Kontrolle der Nacharbeit, dann Freigabe (Merge) bei größeren Änderungen erneut prüfen
Abb. A-7: Ablauf eines Code-Reviews

Vorteile: findet Logik- und Designfehler früh und günstig (bevor getestet wird) · prüft Verständlichkeit, Wartbarkeit und Einhaltung der Richtlinien – das kann kein Test · Wissenstransfer, mehrere kennen den Code (weniger Abhängigkeit von Einzelnen) · Lerneffekt für Einsteiger · einheitlicher Stil · findet auch Sicherheitslücken und fehlende Fehlerbehandlung.

Nachteile/Grenzen: kostet Zeit von erfahrenen Entwicklern · Ergebnis hängt von Sorgfalt und Erfahrung der Reviewer ab · bei sehr großen Änderungen oberflächlich · kann als Kontrolle/Kritik empfunden werden (konstruktive Feedbackkultur nötig) · kann das tatsächliche Laufzeitverhalten nicht nachweisen.

Pair Programming: Zwei Entwickler arbeiten an einem Rechner; der Driver schreibt den Code, der Navigator prüft laufend, denkt voraus und achtet auf Fehler; die Rollen wechseln regelmäßig. Es ist damit ein „Review in Echtzeit“. Vorteile: weniger Fehler, besseres Design, Wissensverteilung, schnelle Einarbeitung neuer Kollegen. Nachteile: zwei Personen für eine Aufgabe (höherer Personalaufwand), anstrengend, Paare müssen harmonieren.

Statische Codeanalyse und Metriken

Werkzeuge wie SonarQube, Checkstyle, SpotBugs oder ESLint („Linter“) untersuchen den Quelltext automatisch – meist in der IDE und in der CI-Pipeline bei jedem Commit.

Findet automatisch: Verstöße gegen Coding-Konventionen (Namen, Formatierung) · ungenutzte Variablen und toten Code · mögliche NullPointerExceptions, nicht geschlossene Ressourcen · doppelten Code · zu hohe Komplexität, zu lange Methoden · bekannte Sicherheitsmuster (z. B. SQL-Abfrage per String-Verkettung) · fehlende Kommentare an öffentlichen Methoden.

Findet nicht: ob der Code die fachlichen Anforderungen erfüllt (falsche Formel, falscher Grenzwert laut Spezifikation) · fehlende Funktionen · ob Namen und Struktur wirklich verständlich und das Design sinnvoll sind · Performance unter realer Last · Bedienbarkeit.

Metriken: Codezeilen (LOC) · zyklomatische Komplexität nach McCabe = Anzahl der binären Entscheidungen + 1 (bzw. Kanten − Knoten + 2 im Kontrollflussgraphen); Werte über 10 gelten als schwer test- und wartbar; die Zahl ist zugleich eine obere Grenze für die Testfälle, die man für vollständige Zweigüberdeckung braucht · Testabdeckung · Anteil duplizierten Codes · Kopplung zwischen Klassen.

Konventionen und Dokumentation

/**
 * Prüft, ob ein Jahr nach dem gregorianischen Kalender ein Schaltjahr ist.
 *
 * @param jahr Jahreszahl, muss größer als 1582 sein
 * @return true, wenn das Jahr ein Schaltjahr ist, sonst false
 * @throws IllegalArgumentException wenn jahr kleiner oder gleich 1582 ist
 * @since 1.2
 */
public static boolean istSchaltjahr(int jahr) { … }

Clean Code

RegelBedeutung
Sprechende NamenName verrät Zweck und Einheit: restlaufzeitTage statt r oder tmp2.
Keine „Magic Numbers“feste Werte als benannte Konstanten (MWST_SATZ) – an einer Stelle änderbar und selbsterklärend.
DRY (Don't Repeat Yourself)keine kopierten Codeblöcke; Gemeinsames in eine Methode/Variable auslagern, sonst müssen Änderungen mehrfach gemacht werden.
Kurze Methoden, eine Aufgabe (SRP)jede Methode/Klasse hat genau eine Verantwortung; lieber mehrere kleine, gut benannte Methoden.
KISS, YAGNIso einfach wie möglich; nichts „auf Vorrat“ programmieren.
Flache VerschachtelungSonderfälle früh abfangen (Guard Clause) statt tief verschachtelter ifs.
Wenige Parameter, keine Seiteneffekteeine Methode berechne… rechnet nur und ändert nicht nebenbei Daten.
Fehlerbehandlung mit Exceptionsstatt geheimer Rückgabecodes; Fehler nicht stillschweigend verschlucken.
PfadfinderregelCode etwas sauberer hinterlassen, als man ihn vorgefunden hat (kontinuierliches Refactoring, abgesichert durch Tests).

Vorher

// berechnet
double b(double n) {
    return n + n * 0.19;   // n plus 19 %
}

Nachher

private static final double MWST_SATZ = 0.19;

/** Liefert den Bruttobetrag zum Nettobetrag (Regelsteuersatz). */
double bruttoBetrag(double nettoBetrag) {
    return nettoBetrag * (1 + MWST_SATZ);
}

Refactoring = Struktur verbessern, ohne das Verhalten zu ändern. Voraussetzung sind Tests (Regressionstest), die vorher und nachher grün sind.

Automatische Prüfungen allein – reicht das?

Jedes Verfahren hat einen „blinden Fleck“: Statische Analyse prüft Form und bekannte Muster, aber keine Fachlogik. Unit-Tests prüfen nur, was jemand als Testfall formuliert hat, und nur einzelne Einheiten – nicht das Zusammenspiel, nicht Last, Bedienbarkeit oder die Anforderungen des Kunden. Eine hohe Testabdeckung sagt nichts über die Qualität der Assertions. Menschliche Reviews erkennen Verständlichkeit, Design- und Anforderungsfehler, verteilen Wissen – sind aber langsamer und nicht vollständig. In der Praxis werden die Verfahren deshalb kombiniert: Automatik als schnelles, lückenloses Sicherheitsnetz in der CI-Pipeline, Reviews und höhere Teststufen für das, was Automatik nicht sieht.

Typische Fehler Bei „Erläutern Sie drei QS-Maßnahmen“ drei Testarten nennen – das ist einseitig; besser Maßnahmen aus verschiedenen Bereichen (Prozess, Werkzeuge, Prüfungen). · Bei „Beurteilen Sie …“ nur Ja/Nein ohne Abwägung: Erwartet werden Argumente für und gegen und ein begründetes Fazit. · Kommentare, die nur den Code wiederholen, als „gute Dokumentation“ verkaufen.
So wird es in der Prüfung gefragt S24 T1 A1b (6 P): drei qualitätssichernde Maßnahmen für die Entwicklung erläutern – die Lösung nannte z. B. standardisiertes Vorgehensmodell, übliche Entwicklungswerkzeuge (IDE, CI/CD), standardisierte Testumgebungen/-verfahren/-daten, Zertifizierung der Mitarbeiter, Verfahrensanweisungen zur Dokumentation, Code-Reviews. · S23 T1 A1e (4 P): QS-Maßnahmen. · W21 T1 A4cb (5 P): Aussage bewerten, dass automatische Code-Reviews und Unit-Tests zur Qualitätssicherung genügen. · W21 T1 A1bb (6 P): Dokumentation einer Erweiterung einer Klassenbibliothek beschreiben.

B · Belegsatz

Enthält nur, was dir auch die IHK beilegen würde bzw. was in der Prüfung auf einem heraustrennbaren Blatt stünde: die Pseudocode-Konventionen (wie im Belegsatz S24) und die Anlagen zur Ausgangssituation (Spezifikationen, Code-Listings mit Zeilennummern, Testdaten, englischer Fachtext). Eine Notationshilfe speziell zum Testen legt die IHK nicht bei. Keine Erklärungen.

Pseudocode, prozedurale Programmierung

PseudocodeBeschreibung
wenn [ Bedingung ] dann
   [ Anweisung ]
sonst
   [ Anweisung ]
Ende wenn
Verzweigung
zähle [ Variable ] von [ Startwert ] bis [ Endwert ]
   [ Schleifeninhalt ]
Ende zähle
Zählschleife (Iteration)
solange [ Bedingung ]
   [ Schleifeninhalt ]
Ende solange
Kopfgesteuerte Schleife
wiederhole
   [ Schleifeninhalt ]
solange [ Bedingung ]
Fußgesteuerte Schleife
:=
Zuweisung
=; <; >; <=; >=; <>
Vergleiche
integer
double
string
boolean
array
Datentypen

In den Listings dieses Blocks gilt außerdem: und, oder, nicht sind logische Operatoren (Auswertung von links nach rechts; steht das Ergebnis fest, wird der Rest nicht mehr ausgewertet); / ist die normale Division (Ergebnis Kommazahl); ausgabe(text) gibt eine Zeile aus, + verkettet dabei Zeichenketten; rückgabe beendet die Funktion. Die Zeilennummern gehören nicht zum Code.

Anlage 1 · Ausgangssituation

Die Aufgaben dieses Blocks beziehen sich auf die folgende Ausgangssituation:

Die VitaPark Fitness GmbH betreibt in Lüneburg und Umgebung fünf Fitnessstudios mit rund 9.000 Mitgliedern. Verträge, Kursbuchungen und der Zutritt werden bisher mit verschiedenen, teilweise veralteten Programmen verwaltet. Ab dem 1. März 2027 soll die neue Plattform „VitaPark Connect“ in Betrieb gehen. Sie besteht aus

Sie sind Auszubildende/r zum Fachinformatiker/zur Fachinformatikerin Anwendungsentwicklung bei der Brückner Digital GmbH in Hannover, die VitaPark Connect entwickelt. Das Team besteht aus sechs Entwicklerinnen und Entwicklern, einer Testerin und einem Product Owner. Der Server wird in Java entwickelt; gearbeitet wird mit Git, Pull-Requests und einer CI-Pipeline, die bei jedem Commit baut und die automatisierten Tests ausführt. Sie sind in die Qualitätssicherung eingebunden: Sie planen Tests, prüfen und korrigieren Code, schreiben Unit-Tests und arbeiten an den Qualitätsanforderungen mit.

Rahmenbedingungen:

Anlage 2 · Klassen und Spezifikationen der zu testenden Methoden (Auszug)

Mitglied - mitgliedNr : integer - name : string - alter : integer - tarif : string - vertragAktiv : boolean - premium : boolean - offenerBetrag : double + istVertragAktiv() : boolean + hatPremium() : boolean + getOffenerBetrag() : double Kurs - name : string - kapazitaet : integer - gebucht : integer + Kurs(name : string, kapazitaet : integer) + buchen(anzahl : integer) : boolean + getFreiePlaetze() : integer (neuer Kurs: gebucht = 0) Termin - kurs : string - datum : string - teilnehmer : integer + getKurs() : string + getDatum() : string + getTeilnehmer() : integer
Abb. B-1: Klassen der Plattform VitaPark Connect (Auszug); für alle Attribute existieren Get-Methoden
MethodeSpezifikation
freiePlaetze(kapazitaet : integer,
  gebucht : integer) : integer
Liefert die Anzahl freier Plätze eines Kurses (kapazitaet − gebucht). Voraussetzungen: kapazitaet > 0 und 0 ≤ gebucht ≤ kapazitaet. Ist eine Voraussetzung verletzt, wird −1 geliefert.
belastungsDurchschnitt(puls : integer[],
  grenze : integer) : double
Liefert den Durchschnitt aller Pulswerte einer Trainingseinheit, die mindestens grenze betragen (Belastungsbereich). Liegt kein Wert im Belastungsbereich, wird 0.0 geliefert.
laengsteSerie(trainiert : boolean[]) : integertrainiert[i] ist true, wenn das Mitglied am Tag i trainiert hat. Liefert die größte Anzahl unmittelbar aufeinanderfolgender Trainingstage. Ist das Array null oder leer, wird eine IllegalArgumentException ausgelöst.
spitzenphasen(besucher : integer[][],
  grenze : integer) : integer
besucher[tag][std] enthält die Anzahl anwesender Mitglieder eines Studios am Tag tag in der Öffnungsstunde std (17, 18, 19, 20 Uhr → Index 0 bis 3). Eine Spitzenphase liegt vor, wenn an einem Tag in mindestens zwei unmittelbar aufeinanderfolgenden Stunden mehr als grenze Mitglieder anwesend sind. Jede Spitzenphase wird genau einmal gezählt. Zwischen zwei Tagen liegt die Nacht – eine Spitzenphase reicht nie über das Tagesende hinaus. Geliefert wird die Anzahl der Spitzenphasen.
beitrag(alter : integer, tarif : string) : doublesiehe Anlage 3 (Beitragsordnung) und Anlage 4 (Listing)
bonuspunkte(minuten : integer[]) : integersiehe Anlage 3 (Bonusprogramm)
kursStatistik(termine : List<Termin>)siehe Anlage 5
zugangPruefen(m : Mitglied,
  bereich : string) : string
siehe Anlage 6

Anlage 3 · Beitrags- und Preisordnung der VitaPark Fitness GmbH (Auszug)

Monatsbeiträge
TarifMonatsbeitragLeistungen
„BASIC“29,90 €Trainingsbereich, Kurse
„PREMIUM“49,90 €zusätzlich Sauna und Getränke
Altersermäßigung auf den Monatsbeitrag
Alter (in vollen Jahren)Ermäßigung
14 bis 17 Jahre50 %
18 bis 64 Jahrekeine
ab 65 Jahre20 %

Mitglied kann man ab 14 Jahren werden. Altersangaben über 120 Jahre gelten als Eingabefehler.

Methode beitrag(alter : integer, tarif : string) : double: liefert den Monatsbeitrag in Euro nach den obigen Tabellen. Bei einem Alter unter 14 oder über 120 sowie bei einem unbekannten oder fehlenden Tarif (null, leere Zeichenkette, jeder andere Wert als „BASIC“ oder „PREMIUM“ in genau dieser Schreibweise) löst die Methode eine IllegalArgumentException aus.

Gast-Tageskarten (für Nichtmitglieder)
LeistungPreis
Tageskarte15,00 € je Karte
Tageskarte ermäßigt (Schüler, Studierende)10,00 € je Karte
Mengenrabatt ab 10 gleichzeitig gekauften Karten10 % auf den Kartenpreis
Sauna-Zuschlag5,00 € je Karte (wird nicht rabattiert)

Kursbuchung mit Gästen: Bei jeder Kursbuchung kann ein Mitglied zusätzlich 0 bis 3 Gäste anmelden.

Bonusprogramm GesundPlus: Für jede Trainingseinheit ab 60 Minuten gibt es 3 Bonuspunkte, für jede Trainingseinheit ab 30 Minuten (aber unter 60 Minuten) 1 Bonuspunkt, für kürzere Einheiten keine Punkte. Die Methode bonuspunkte(minuten : integer[]) : integer erhält die Dauer aller Trainingseinheiten eines Monats in Minuten und liefert die Summe der Bonuspunkte.

Anlage 4 · Listing der Methode beitrag (Java)

01 public double beitrag(int alter, String tarif) {
02     if (alter < 14 || alter > 120) {
03         throw new IllegalArgumentException("Alter ungültig");
04     }
05     double grundbeitrag;
06     if (tarif.equals("BASIC")) {
07         grundbeitrag = 29.90;
08     } else if (tarif.equals("PREMIUM")) {
09         grundbeitrag = 49.90;
10     } else {
11         throw new IllegalArgumentException("Tarif unbekannt");
12     }
13     if (alter <= 17) {
14         return grundbeitrag * 0.5;
15     }
16     if (alter > 65) {
17         return grundbeitrag * 0.8;
18     }
19     return grundbeitrag;
20 }

Anlage 5 · Prozedur kursStatistik mit Testdaten

Die Studioleitung erhält eine Statistik, wie gut die Kurse besucht waren. Die Termine liegen in einer Liste termine : List<Termin> (Klasse Termin siehe Anlage 2), aufsteigend sortiert nach Kursname. Für jeden Kurs sollen die Anzahl der Termine, die höchste Teilnehmerzahl eines Termins und die durchschnittliche Teilnehmerzahl ausgegeben werden, zum Schluss die Anzahl aller Termine und die durchschnittliche Teilnehmerzahl über alle Termine. Ist die Liste leer, wird nach der Überschrift nur die Zeile „Keine Termine vorhanden“ ausgegeben. Kommazahlen werden mit einer Nachkommastelle ausgegeben.

01 prozedur kursStatistik(termine : List<Termin>)
02   ausgabe("Kursstatistik")
03   kurs : string := termine.get(0).getKurs()
04   anzahl : integer := 0
05   summe : integer := 0
06   max : integer := 0
07   anzahlGesamt : integer := 0
08   summeGesamt : integer := 0
09   zähle i von 0 bis termine.size() - 1
10     t : Termin := termine.get(i)
11     wenn t.getKurs() <> kurs dann
12       ausgabe(kurs + ": " + anzahl + " Termine, max. " + max
13               + ", Ø " + summe / anzahl)
14       anzahlGesamt := anzahlGesamt + anzahl
15       summeGesamt := summeGesamt + summe
16       kurs := t.getKurs()
17       anzahl := 0
18       summe := 0
19     Ende wenn
20     anzahl := anzahl + 1
21     summe := summe + t.getTeilnehmer()
22     wenn t.getTeilnehmer() > max dann
23       max := t.getTeilnehmer()
24     Ende wenn
25   Ende zähle
26   ausgabe("Gesamt: " + anzahlGesamt + " Termine, Ø "
27           + summeGesamt / anzahl)
28 Ende prozedur
Testdaten (Liste termine)
Indexkursdatumteilnehmer
0Aqua-Fitness03.11.202614
1Aqua-Fitness10.11.202618
2Rückenfit04.11.202610
3Rückenfit11.11.202612
4Rückenfit18.11.20268
5Yoga05.11.202616
6Yoga12.11.202613

Erwartete Ausgabe für diese Testdaten:

Kursstatistik Aqua-Fitness: 2 Termine, max. 18, Ø 16.0 Rückenfit: 3 Termine, max. 12, Ø 10.0 Yoga: 2 Termine, max. 16, Ø 14.5 Gesamt: 7 Termine, Ø 13.0

Anlage 6 · Listing der Methode zugangPruefen (Java)

Die Methode wird aufgerufen, wenn ein Mitglied an einem Drehkreuz seinen QR-Code scannt. bereich ist „Trainingsbereich“ (Drehkreuz am Eingang) oder „Sauna“. Die Rückgabe wird auf dem Display des Drehkreuzes angezeigt; das Drehkreuz öffnet, wenn die Meldung mit „Zutritt“ beginnt. Mitglieder mit offenem Betrag erhalten Zutritt, aber einen Hinweis. Versuche ohne aktiven Vertrag werden protokolliert. Die Kommentare B1 … B4 kennzeichnen Bedingungen, A1 … A5 Anweisungen.

01 public String zugangPruefen(Mitglied m, String bereich) {
02     String meldung = "Kein Zutritt";
03     if (m.istVertragAktiv()) {                          // B1
04         meldung = "Zutritt Trainingsbereich";           // A1
05         if (bereich.equals("Sauna")) {                  // B2
06             if (m.hatPremium()) {                       // B3
07                 meldung = "Zutritt Sauna";              // A2
08             } else {
09                 meldung = "Sauna nur mit Premium";      // A3
10             }
11         }
12         if (m.getOffenerBetrag() > 0) {                 // B4
13             meldung = meldung + " (Zahlung offen)";     // A4
14         }
15     } else {
16         protokolliereVersuch(m);                        // A5
17     }
18     return meldung;
19 }

Anlage 7 · Englischer Fachtext (Auszug aus dem Testhandbuch von Brückner Digital)

Measuring test coverage

Code coverage tells a development team how much of its source code is actually executed while the test suite is running. It is usually reported as a percentage and measured automatically by coverage tools such as JaCoCo for Java.

Statement coverage is the simplest metric. It counts how many of the executable statements have been run at least once. A test suite that reaches 100 % statement coverage has executed every line of code – but not necessarily every outcome of every decision. An if statement without an else part, for example, can be fully covered by a single test in which the condition is true.

Branch coverage, also called decision coverage, is stricter. Each possible outcome of every decision, true as well as false, has to be taken at least once. Complete branch coverage therefore always includes complete statement coverage, whereas the reverse is not true.

Path coverage is the strongest of the three metrics. A path is a sequence of statements that starts at the entry point of a method and ends at one of its exit points. Full path coverage requires every possible path to be executed at least once, which in turn guarantees full branch coverage. The number of paths grows very quickly: every independent decision doubles it, and a loop can in theory produce an unlimited number of paths. In practice, path coverage is therefore only achievable for small methods, or the number of loop iterations has to be limited.

Keep in mind that high coverage does not prove that the code is correct. Coverage only shows which code was executed, not whether the results were checked by meaningful assertions – and it can never reveal functionality that is missing completely.

Anlage 8 · Auszug aus dem Testframework JUnit 5

AnweisungBeschreibung
@Testkennzeichnet eine Methode als Testmethode
assertEquals(expected, actual)Prüft, ob die Werte für expected (erwartet) und actual (tatsächlich) gleich sind. Ist dies nicht der Fall, schlägt der Test fehl.
assertEquals(expected, actual, delta)wie oben für Kommazahlen; die Werte gelten als gleich, wenn sie sich höchstens um delta unterscheiden
assertTrue(bedingung)
assertFalse(bedingung)
Prüft, ob die Bedingung wahr bzw. falsch ist. Ist dies nicht der Fall, schlägt der Test fehl.
assertThrows(Ausnahme.class,
  () -> aufruf)
Führt den Aufruf aus. Der Test ist erfolgreich, wenn dabei eine Ausnahme vom angegebenen Typ ausgelöst wird; sonst schlägt er fehl.

Benötigte Importe: import org.junit.jupiter.api.Test; und import static org.junit.jupiter.api.Assertions.*;

C · Aufgaben

Alle Aufgaben beziehen sich auf die Ausgangssituation in Anlage 1. Spezifikationen, Listings und Testdaten stehen in den Anlagen 2 bis 8. Algorithmen und Korrekturen dürfen in Pseudocode nach den Konventionen des Belegsatzes oder in Java formuliert werden.

TQ-01 · Testarten

Aufgabe TQ-01.1 ★☆☆ Grundlagen 6 Punkte

Im Projekt VitaPark Connect werden Tests auf verschiedenen Stufen durchgeführt.

4 Pa) Ordnen Sie den folgenden Situationen jeweils die Teststufe zu und geben Sie an, gegen welches Dokument bzw. welche Entwurfsphase des V-Modells dabei geprüft wird.
Nr.SituationTeststufePrüfgrundlage
1Eine Entwicklerin prüft die Methode beitrag (Anlage 4) isoliert mit eigenen Testdaten, bevor sie den Code in das gemeinsame Repository übernimmt.
2Es wird geprüft, ob die App eine Kursbuchung korrekt über die REST-Schnittstelle an den Server überträgt und der Server sie in der Datenbank speichert.
3Die Testerin prüft das vollständig installierte System in einer produktionsnahen Testumgebung gegen alle Anforderungen des Pflichtenhefts, einschließlich der Antwortzeiten.
4Die Geschäftsführung der VitaPark Fitness GmbH spielt am 15.02.2027 typische Abläufe aus dem Studioalltag durch und entscheidet über die Freigabe.
2 Pb) Erläutern Sie den Unterschied zwischen statischem und dynamischem Testen und nennen Sie je ein Beispiel aus dem Projekt.

Angelehnt an: W23 Teil 1, Aufgabe 1d (Zusammenspiel der Teststufen) und W21 Teil 1, Aufgabe 4

Aufgabe TQ-01.2 ★★☆ Anwendung 10 Punkte
4 Pa) Für die Methode zugangPruefen (Anlage 6) sollen Testfälle entworfen werden. Erläutern Sie den Unterschied zwischen einem Black-Box- und einem White-Box-Test und nennen Sie zwei Vorteile des White-Box-Tests gegenüber dem Black-Box-Test.
3 Pb) Nach einer Änderung an der Beitragsberechnung meldet eine Studioleitung, dass die bereits abgenommene Kursbuchung plötzlich mit einer Fehlermeldung abbricht. Erläutern Sie, mit welcher Testart dieser Fehler vor der Auslieferung hätte entdeckt werden können, und begründen Sie, warum diese Testart automatisiert werden sollte.
3 Pc) Zu Spitzenzeiten werden bis zu 50 Check-ins pro Minute erwartet (Anlage 1). Nennen Sie eine geeignete Testart, um das Verhalten des Servers unter dieser Belastung zu prüfen, und beschreiben Sie das Vorgehen.

Angelehnt an: S24 Teil 2, Aufgabe 3a (Vorteile White-Box, Regressionstest) und W21 Teil 1, Aufgabe 4d

Aufgabe TQ-01.3 ★★★ Prüfungsniveau 20 Punkte

Bis zur Abnahme am 15.02.2027 bleiben nur wenige Monate. Der Product Owner beauftragt Sie, die Tests für VitaPark Connect zu planen und ein Testkonzept zu erstellen.

6 Pa) Beschreiben Sie drei Inhalte, die in einem Testkonzept für VitaPark Connect festgelegt werden sollten.
4 Pb) Da viele Mitglieder über 60 Jahre alt sind und erstmals eine solche App nutzen, soll die App einem Usability-Test unterzogen werden. Beschreiben Sie zwei Methoden, mit denen ein Usability-Test durchgeführt werden kann.
3 Pc) Nach jedem nächtlichen Deployment auf die Testumgebung soll automatisch ein Smoke-Test laufen. Erläutern Sie den Begriff Smoke-Test und nennen Sie zwei Prüfungen, die dieser Smoke-Test für VitaPark Connect enthalten sollte.
d) Die Trainingsdaten werden im JSON-Format an das Bonusprogramm „GesundPlus“ übertragen (Anlage 1). Die Krankenkasse hat dafür eine Schnittstellenspezifikation mit einem JSON-Schema veröffentlicht.
3 Pda) Beschreiben Sie zwei Maßnahmen, mit denen sichergestellt werden kann, dass die Schnittstelle der Spezifikation entspricht.
4 Pdb) Ein Kollege meint: „Wenn jede erzeugte Datei erfolgreich gegen das JSON-Schema validiert wird, ist die Schnittstelle ausreichend getestet.“ Nehmen Sie begründet Stellung.

Angelehnt an: W23 Teil 1, Aufgabe 1d (Testkonzept), W21 Teil 1, Aufgabe 3ac (Usability-Test) und W25 Teil 1, Aufgabe 3b (Konformität zur Spezifikation, XSD-Validierung)

TQ-02 · Code analysieren / Fehler finden

Aufgabe TQ-02.1 ★☆☆ Grundlagen 5 Punkte
3 Pa) Ordnen Sie die folgenden Fehler im Java-Code von VitaPark Connect jeweils der richtigen Fehlerart zu (Kreuz setzen).
Nr.FehlerSyntax­fehlerLaufzeit­fehlerLogik­fehler
1In der Zeile int anzahl = 0 fehlt das Semikolon.
2In einer Schleife wird auf puls[puls.length] zugegriffen.
3Die Summe der Teilnehmer wird mit summe = summe - t.getTeilnehmer() gebildet.
4Ein Rabatt von 20 % wird als preis * 0.2 statt preis * 0.8 berechnet.
5Statt return wurde retrun geschrieben.
6Eine Methode erhält null statt einer Liste und ruft termine.size() auf.
2 Pb) Beschreiben Sie, warum Logikfehler weder beim Übersetzen noch durch einen Programmabbruch auffallen, und wie man sie trotzdem findet.

Angelehnt an: W25 Teil 2, Aufgabe 3bb (semantische Fehler)

Aufgabe TQ-02.2 ★★☆ Anwendung 10 Punkte

Für die Trainingsauswertung in der App wurde die Methode belastungsDurchschnitt implementiert (Spezifikation in Anlage 2: Durchschnitt aller Pulswerte, die mindestens grenze betragen; kein solcher Wert → 0.0).

01 public double belastungsDurchschnitt(int[] puls, int grenze) {
02     int summe = 0;
03     int anzahl = 0;
04     for (int i = 1; i < puls.length; i++) {
05         if (puls[i] > grenze) {
06             summe = summe + puls[i];
07             anzahl++;
08         }
09     }
10     if (anzahl == 0) {
11         return 0.0;
12     }
13     return (double) summe / puls.length;
14 }
3 Pa) Führen Sie einen Schreibtischtest mit puls = {150, 120, 140, 160, 135} und grenze = 140 durch. Geben Sie das tatsächliche und das laut Spezifikation erwartete Ergebnis an. Nicht benötigte Zeilen bleiben leer.
ipuls[i]Bedingung Zeile 05summeanzahl
3 Pb) Nennen Sie die drei Fehler der Methode mit Zeilennummer und beschreiben Sie jeweils ihre Auswirkung.
2 Pc) Geben Sie die korrigierten Zeilen an.
2 Pd) Geben Sie Testdaten an, mit denen die fehlerhafte Methode trotzdem das richtige Ergebnis liefert, und erläutern Sie, was daraus für das Testen folgt.

Angelehnt an: W25 Teil 2, Aufgabe 3b (fehlerhafte Funktion durchspielen und korrigieren)

Aufgabe TQ-02.3 ★★★ Prüfungsniveau 25 Punkte

Die Prozedur kursStatistik (Anlage 5) wurde von einem Praktikanten geschrieben und soll vor der Freigabe getestet werden. Verwenden Sie die Testdaten und die erwartete Ausgabe aus Anlage 5.

6 Pa) Überprüfen Sie die Prozedur mit den Testdaten. Tragen Sie den Werteverlauf in die Datenverlaufstabelle ein und geben Sie die tatsächliche Ausgabe an.
TypVariableWerteverlauf
integeri
stringkurs
integeranzahl
integersumme
integermax
integeranzahlGesamt
integersummeGesamt

Tatsächliche Ausgabe:

6 Pb) Nennen Sie drei Fehler mit Zeilennummer und beschreiben Sie jeweils ihre Auswirkung auf die Ausgabe.
8 Pc) Geben Sie Korrekturen an, sodass für die Testdaten die erwartete Ausgabe aus Anlage 5 erzeugt wird. Geben Sie jeweils an, welche Zeile Sie ersetzen bzw. nach welcher Zeile Sie Anweisungen einfügen.
3 Pd) Beschreiben Sie, was beim Aufruf mit einer leeren Liste geschieht, und ergänzen Sie die Prozedur so, dass sie sich dann wie in Anlage 5 gefordert verhält.
2 Pe) Nennen Sie zwei Testarten, die nach der Korrektur durchgeführt werden sollten, und begründen Sie jeweils kurz.

Angelehnt an: S23 Teil 2, Aufgabe 3a (Jahresstatistik mit Datenverlaufstabelle, Fehler nennen, Code korrigieren und erweitern)

TQ-03 · Unit-Test / Überdeckungsmaße

Aufgabe TQ-03.1 ★☆☆ Grundlagen 6 Punkte

Die Methoden der Klasse Kurs (Anlage 2) sollen mit Unit-Tests geprüft werden.

2 Pa) Beschreiben Sie, was ein Unit-Test ist und wozu er verwendet wird.
2 Pb) Nennen und beschreiben Sie zwei Eigenschaften, die ein Unit-Test erfüllen sollte.
2 Pc) Ordnen Sie den mit (1) bis (3) markierten Zeilen des folgenden Tests die Phasen des Arrange-Act-Assert-Musters zu und beschreiben Sie kurz die Aufgabe jeder Phase.
@Test
void buchungVerringertFreiePlaetze() {
    Kurs kurs = new Kurs("Yoga", 12);          // (1)
    kurs.buchen(3);                            // (2)
    assertEquals(9, kurs.getFreiePlaetze());   // (3)
}

Angelehnt an: S22 Teil 2, Aufgabe 2a und W25 Teil 2, Aufgabe 3aa

Aufgabe TQ-03.2 ★★☆ Anwendung 12 Punkte

Für die Kursbuchung wurde die Methode freiePlaetze implementiert (Spezifikation in Anlage 2). Ein Kollege hat dazu einen Unit-Test geschrieben (JUnit-Auszug in Anlage 8).

01 public int freiePlaetze(int kapazitaet, int gebucht) {
02     int frei = -1;
03     if (kapazitaet > 0 && gebucht > 0) {
04         if (gebucht < kapazitaet) {
05             frei = kapazitaet - gebucht;
06         }
07     }
08     return frei;
09 }
@Test
void testeFreiePlaetze() {
    assertEquals(5, freiePlaetze(20, 15));      // Testfall 1
    assertEquals(20, freiePlaetze(20, 0));      // Testfall 2
    assertEquals(0, freiePlaetze(20, 20));      // Testfall 3
    assertEquals(-1, freiePlaetze(20, 21));     // Testfall 4
    assertEquals(-1, freiePlaetze(0, 0));       // Testfall 5
    assertEquals(19, freiePlaetze(20, 1));      // Testfall 6
}
6 Pa) Ermitteln Sie für jeden Testfall den Rückgabewert der Methode und ob der Testfall erfolgreich ist (OK) oder fehlschlägt (Fehler). Betrachten Sie dabei jeden Testfall für sich.
TestfallRückgabewert der MethodeErgebnis des Tests (OK / Fehler)
1
2
3
4
5
6
3 Pb) Korrigieren Sie die Methode so, dass sie der Spezifikation entspricht und alle Testfälle erfolgreich sind.
3 Pc) Beim Ausführen der Testmethode testeFreiePlaetze mit der ursprünglichen Methode meldet JUnit nur einen einzigen fehlgeschlagenen Testfall. Erläutern Sie die Ursache und beschreiben Sie, wie der Test besser aufgebaut werden kann.

Angelehnt an: S22 Teil 2, Aufgabe 2b (assertEquals-Testfälle auswerten, Bedingungen korrigieren)

Aufgabe TQ-03.3 ★★★ Prüfungsniveau 25 Punkte

Die Methode zugangPruefen (Anlage 6) steuert die Drehkreuze und ist damit sicherheitsrelevant. Laut Testkonzept soll für sie eine möglichst hohe Testabdeckung erreicht werden. Im Testhandbuch von Brückner Digital werden die Überdeckungsmaße auf Englisch beschrieben (Anlage 7).

9 Pa) Erläutern Sie mithilfe des Fachtextes (Anlage 7) die Anweisungsüberdeckung, die Zweigüberdeckung und die Pfadüberdeckung. Gehen Sie jeweils auch auf das Verhältnis zu den anderen Überdeckungsmaßen ein.
5 Pb) Zeichnen Sie den Kontrollflussgraphen der Methode zugangPruefen. Beschriften Sie die Knoten mit B1 … B4 bzw. A1 … A5 (Anfangs- und Rückgabeanweisung dürfen als „Start“ und „Ende“ bezeichnet werden) und die Kanten an den Bedingungen mit w (wahr) bzw. f (falsch).
4 Pc) Geben Sie die minimale Anzahl der Testfälle für eine vollständige Anweisungsüberdeckung und für eine vollständige Zweigüberdeckung an. Geben Sie für die Zweigüberdeckung die Testfälle an (Werte für Vertrag aktiv, Premium, offener Betrag, Bereich).
5 Pd) Notieren Sie alle Pfade, die durchlaufen werden müssen, um eine vollständige Pfadüberdeckung zu erreichen. Geben Sie dazu je Pfad alle durchlaufenen Bedingungen (B) und Anweisungen (A) in der Reihenfolge ihrer Abarbeitung an. Beispiel für die Schreibweise: B1, A1, B2, … (das Beispiel ist kein möglicher Pfad). Nicht benötigte Zeilen bleiben leer.
NummerPfad
1
2
3
4
5
6
7
8
2 Pe) Laut Fachtext beweist eine hohe Überdeckung nicht, dass der Code korrekt ist. Erläutern Sie dies an einem Beispiel zur Methode zugangPruefen.

Angelehnt an: S24 Teil 2, Aufgabe 3b/3c (Überdeckungsmaße aus englischem Fachtext, alle Pfade notieren) und W22 Teil 2, Aufgabe 2ac

TQ-04 · Qualitätsmerkmale ISO/IEC 25010

Aufgabe TQ-04.1 ★☆☆ Grundlagen 6 Punkte

Im Pflichtenheft von VitaPark Connect stehen unter anderem die folgenden nicht-funktionalen Anforderungen.

6 POrdnen Sie jeder Anforderung das passende Qualitätsmerkmal nach ISO/IEC 25010 zu.
Nr.AnforderungQualitätsmerkmal
1Die Auslastungsanzeige der App wird nach dem Antippen in höchstens 2 Sekunden aktualisiert.
2Fällt die Verbindung zum Server aus, kann das Drehkreuz die Mitgliedskarten der letzten 24 Stunden weiterhin offline prüfen.
3Neue Trainer können nach einer 15-minütigen Einweisung selbstständig Kurse anlegen.
4Trainingsdaten können von Fitnessarmbändern verschiedener Hersteller übernommen werden.
5Ein neuer Tarif kann ergänzt werden, indem nur das Modul „Beitragsberechnung“ geändert wird.
6Pulsdaten eines Mitglieds können nur von ihm selbst und seinem Trainer eingesehen werden.

Angelehnt an: W21 Teil 1, Aufgabe 4ca und S26 Teil 1, Aufgabe 4a

Aufgabe TQ-04.2 ★★☆ Anwendung 8 Punkte
3 Pa) Beschreiben Sie das Qualitätsmerkmal Zuverlässigkeit nach ISO/IEC 25010 und erläutern Sie zwei Untermerkmale am Beispiel des Check-ins am Drehkreuz.
3 Pb) Beschreiben Sie das Qualitätsmerkmal Wartbarkeit, nennen Sie zwei Untermerkmale und begründen Sie, warum dieses Merkmal für Brückner Digital bei VitaPark Connect besonders wichtig ist.
2 Pc) Im Lastenheft steht: „Die App soll schnell und einfach zu bedienen sein.“ Formulieren Sie daraus zwei messbare und damit prüfbare Anforderungen.

Angelehnt an: S26 Teil 1, Aufgabe 4a (Zuverlässigkeit) und W21 Teil 1, Aufgabe 4ca (Effizienz, Änderbarkeit)

Aufgabe TQ-04.3 ★★★ Prüfungsniveau 17 Punkte

Die VitaPark Fitness GmbH möchte die Qualitätsanforderungen an das Teilsystem „Check-in am Drehkreuz“ vertraglich festlegen: Das Mitglied hält den QR-Code der App an den Scanner, der Server prüft den Zugang mit zugangPruefen (Anlage 6), das Drehkreuz öffnet. Ein Mitarbeiter der VitaPark legt dazu eine ältere Checkliste vor, die auf der Norm ISO/IEC 9126 beruht.

3 Pa) Nennen Sie die sechs Qualitätsmerkmale der ISO/IEC 9126.
2 Pb) Nennen Sie die zwei Qualitätsmerkmale, die in der Nachfolgenorm ISO/IEC 25010 (Fassung 2011) als eigenständige Hauptmerkmale hinzugekommen sind.
9 Pc) Ergänzen Sie die Tabelle für das Teilsystem „Check-in am Drehkreuz“. Geben Sie je Merkmal eine konkrete Anforderung, ein messbares Abnahmekriterium und die Art der Prüfung (Testart, Vorgehen) an.
Merkmalkonkrete Anforderungmessbares AbnahmekriteriumPrüfung
Zuverlässigkeit
Leistungs­effizienz
Sicherheit
3 Pd) Erläutern Sie an einem Beispiel aus VitaPark Connect einen Zielkonflikt zwischen zwei Qualitätsmerkmalen.

Angelehnt an: S23 Teil 1, Aufgabe 2a (Qualitätsmerkmale nach ISO 9126) und S26 Teil 1, Aufgabe 4a

TQ-05 · Schreibtischtest

Aufgabe TQ-05.1 ★☆☆ Grundlagen 5 Punkte

Die Bonuspunkte für das Programm GesundPlus (Anlage 3) werden mit folgender Funktion berechnet:

01 funktion bonuspunkte(minuten : integer[]) : integer
02   punkte : integer := 0
03   zähle i von 0 bis minuten.length - 1
04     wenn minuten[i] >= 60 dann
05       punkte := punkte + 3
06     sonst
07       wenn minuten[i] >= 30 dann
08         punkte := punkte + 1
09       Ende wenn
10     Ende wenn
11   Ende zähle
12   rückgabe punkte
13 Ende funktion
1 Pa) Erläutern Sie, was man unter einem Schreibtischtest versteht.
3 Pb) Führen Sie einen Schreibtischtest für minuten = [45, 70, 20, 60, 30] durch. Tragen Sie das Ergebnis der Bedingungen als wahr/falsch ein; wird eine Bedingung nicht geprüft, tragen Sie „–“ ein.
iminuten[i]Bedingung Zeile 04Bedingung Zeile 07punkte
––––0
1 Pc) Geben Sie den Rückgabewert an und prüfen Sie, ob er der Regel in Anlage 3 entspricht.

Angelehnt an: W22 Teil 2, Aufgabe 2aa und S23 Teil 2, Aufgabe 3a (Schreibtischtest)

Aufgabe TQ-05.2 ★★☆ Anwendung 10 Punkte

Für die Personalplanung zählt die Funktion spitzenphasen (Spezifikation in Anlage 2), wie oft ein Studio stark ausgelastet war.

01 funktion spitzenphasen(besucher : integer[][], grenze : integer) : integer
02   anzahl : integer := 0
03   folge : integer := 0
04   zähle tag von 0 bis besucher.length - 1
05     zähle std von 0 bis besucher[tag].length - 1
06       wenn besucher[tag][std] > grenze dann
07         folge := folge + 1
08         wenn folge = 2 dann
09           anzahl := anzahl + 1
10         Ende wenn
11       sonst
12         folge := 0
13       Ende wenn
14     Ende zähle
15   Ende zähle
16   rückgabe anzahl
17 Ende funktion
Testdaten besucher (Studio Lüneburg-Mitte), grenze = 80
tagstd 0 (17 Uhr)std 1 (18 Uhr)std 2 (19 Uhr)std 3 (20 Uhr)
0 (Mo)40859095
1 (Di)70826088
2 (Mi)91509697
6 Pa) Führen Sie einen Schreibtischtest mit den Testdaten durch. Notieren Sie je Durchlauf der inneren Schleife eine Zeile.
tagstdbesucher[tag][std]Bedingung Zeile 06folgeanzahl
––––00
2 Pb) Geben Sie das tatsächliche Ergebnis und das laut Spezifikation erwartete Ergebnis an. Begründen Sie die Abweichung.
2 Pc) Nennen Sie den Fehler mit Zeilennummer und korrigieren Sie die Funktion.

Angelehnt an: S23 Teil 2, Aufgabe 3a (Schreibtischtest über verschachtelte Daten, Fehler finden)

Aufgabe TQ-05.3 ★★★ Prüfungsniveau 20 Punkte

Die App zeigt Mitgliedern an, wie viele Tage sie höchstens am Stück trainiert haben. Dafür wurde die Methode laengsteSerie implementiert (Spezifikation in Anlage 2).

01 public int laengsteSerie(boolean[] trainiert) {
02     if (trainiert == null) {
03         throw new IllegalArgumentException("keine Daten");
04     }
05     int serie = 0;
06     int max = 0;
07     for (int i = 0; i < trainiert.length; i++) {
08         if (trainiert[i]) {
09             serie++;
10         } else {
11             if (serie > max) {
12                 max = serie;
13             }
14             serie = 0;
15         }
16     }
17     return max;
18 }
6 Pa) Testen Sie die Methode mit den folgenden Testdaten (W = true, F = false). Tragen Sie das laut Spezifikation erwartete und das tatsächliche Ergebnis ein.
TFTestdaten trainierterwartetes Ergebnistatsächliches Ergebnis
1{W, W, F, W, W, W, F}
2{W, F, W, W, W, W}
3{F, F, F}
4{W, W, W}
5{} (leeres Array)
6null
5 Pb) Für die Anzeige „aktuelle Serie ab Tag i“ gibt es eine rekursive Hilfsfunktion. Führen Sie einen Schreibtischtest für den Aufruf serieAb(t, 3) mit t = {F, W, F, W, W, W} durch. Tragen Sie jeden Aufruf (auch die rekursiven) in eine eigene Zeile ein und geben Sie das Ergebnis an. Nicht benötigte Zeilen bleiben leer.
01 funktion serieAb(t : boolean[], i : integer) : integer
02   wenn i >= t.length oder nicht t[i] dann
03     rückgabe 0
04   Ende wenn
05   rückgabe 1 + serieAb(t, i + 1)
06 Ende funktion
Aufrufii >= t.lengtht[i]Rückgabewert
1
2
3
4
5
5 Pc) Nennen Sie die beiden Fehler der Methode laengsteSerie mit Zeilennummer und korrigieren Sie die Methode.
4 Pd) Geben Sie an, welche Testfälle aus a) mindestens nötig sind, damit jede Anweisung der gegebenen Methode mindestens einmal ausgeführt wird. Begründen Sie Ihre Auswahl.

Angelehnt an: W25 Teil 2, Aufgabe 3b (erwartetes und tatsächliches Testergebnis, zwei Fehler korrigieren), W22 Teil 2, Aufgabe 2a (Schreibtischtest einer Rekursion) und S23 Teil 2, Aufgabe 3b

TQ-06 · Äquivalenzklassen / Testfälle

Aufgabe TQ-06.1 ★☆☆ Grundlagen 5 Punkte

Bei einer Kursbuchung kann ein Mitglied zusätzlich 0 bis 3 Gäste anmelden (Anlage 3). Die Anzahl wird in der App in ein Textfeld eingegeben.

3 Pa) Bilden Sie die gültigen und ungültigen Äquivalenzklassen für diese Eingabe und geben Sie je einen Repräsentanten an.
ÄKgültig / ungültigBeschreibungRepräsentant
1
2
3
4
2 Pb) Geben Sie die Testwerte an, die sich aus der Grenzwertanalyse ergeben, und begründen Sie, warum Grenzwerte zusätzlich getestet werden.

Angelehnt an: S22 Teil 2, Aufgabe 2bc (Testdaten aus Äquivalenzklassen)

Aufgabe TQ-06.2 ★★☆ Anwendung 12 Punkte

Die Methode beitrag(alter : integer, tarif : string) : double berechnet den Monatsbeitrag nach der Beitragsordnung (Anlage 3). Bevor der Code geprüft wird, sollen Black-Box-Testfälle aus der Spezifikation abgeleitet werden.

4 Pa) Bilden Sie für beide Parameter die gültigen und ungültigen Äquivalenzklassen.
Parametergültige Äquivalenzklassenungültige Äquivalenzklassen
alter
tarif
5 Pb) Erstellen Sie eine Testfalltabelle mit möglichst wenigen Testfällen, in der jede Äquivalenzklasse mindestens einmal vorkommt. Geben Sie jeweils das erwartete Ergebnis an. Nicht benötigte Zeilen bleiben leer.
Nr.altertarifabgedeckte Äquivalenzklassenerwartetes Ergebnis
1
2
3
4
5
6
7
8
3 Pc) Ergänzen Sie die Testfälle, die sich aus der Grenzwertanalyse für den Parameter alter ergeben (Tarif jeweils „BASIC“), mit dem erwarteten Ergebnis.
altererwartetes Ergebnisaltererwartetes Ergebnis

Angelehnt an: S22 Teil 2, Aufgabe 2bc (Äquivalenzklassen) und W25 Teil 2, Aufgabe 3ba (Testdaten mit Sonderfällen)

Aufgabe TQ-06.3 ★★★ Prüfungsniveau 18 Punkte

Die Methode beitrag wurde implementiert (Anlage 4). Sie gehört zur Klasse Beitragsrechner, die einen parameterlosen Konstruktor hat. Die Testerin hat folgende Testfälle festgelegt:

TFaltertariferwartetes Ergebnis
TF116„PREMIUM“24.95
TF240„BASIC“29.90
TF365„BASIC“23.92
TF413„BASIC“IllegalArgumentException
TF530„GOLD“IllegalArgumentException
TF630nullIllegalArgumentException
6 Pa) Setzen Sie die Testfälle TF1 bis TF6 als JUnit-5-Testklasse um (Anlage 8). Verwenden Sie für Kommazahlen eine Toleranz von 0.001.
4 Pb) Ermitteln Sie, welche Testfälle mit der Methode aus Anlage 4 fehlschlagen. Begründen Sie jeweils mit Angabe der Zeile, was die Methode stattdessen tut.
2 Pc) Korrigieren Sie die betroffenen Zeilen.
3 Pd) Für die korrigierte Methode soll eine vollständige Anweisungsüberdeckung erreicht werden. Ermitteln Sie die kleinste Teilmenge von TF1 bis TF6, die dafür genügt, und begründen Sie Ihre Auswahl.
3 Pe) Ein Kollege schlägt vor, statt ausgewählter Testfälle automatisiert alle Alterswerte von 0 bis 130 mit beiden Tarifen zu testen. Beurteilen Sie den Vorschlag.

Angelehnt an: S22 Teil 2, Aufgabe 2b (Unit-Test, Bedingungen korrigieren, Äquivalenzklassen) und S23 Teil 2, Aufgabe 3bc (Testdaten für volle Anweisungsüberdeckung)

TQ-07 · Codequalität / Reviews

Aufgabe TQ-07.1 ★☆☆ Grundlagen 6 Punkte

Die Geschäftsführung der VitaPark Fitness GmbH fragt, wie Brückner Digital die Qualität der Software schon während der Entwicklung sicherstellt.

6 PErläutern Sie drei qualitätssichernde Maßnahmen im Entwicklungsprozess.

Angelehnt an: S24 Teil 1, Aufgabe 1b und S23 Teil 1, Aufgabe 1e

Aufgabe TQ-07.2 ★★☆ Anwendung 10 Punkte

Die folgende Methode berechnet den Preis für Gast-Tageskarten nach der Preisliste in Anlage 3 (n = Anzahl Karten, e = ermäßigt, s = mit Sauna). Sie liefert korrekte Ergebnisse, fiel aber im Code-Review negativ auf.

01 // Preis
02 public double p(int n, boolean e, boolean s) {
03     double x = 0;
04     if (e == true) {
05         x = 10.0 * n;
06         if (n >= 10) {
07             x = 10.0 * n - 10.0 * n * 0.1;
08         }
09     } else {
10         x = 15.0 * n;
11         if (n >= 10) {
12             x = 15.0 * n - 15.0 * n * 0.1;
13         }
14     }
15     if (s == true) x = x + 5.0 * n;   // plus 5 mal n
16     return x;
17 }
4 Pa) Nennen Sie vier Verstöße gegen Clean-Code-Regeln bzw. Coding-Konventionen mit Zeilenangabe.
4 Pb) Überarbeiten Sie die Methode nach Clean-Code-Regeln. Das Verhalten soll unverändert bleiben.
2 Pc) Ergänzen Sie für die überarbeitete Methode einen Javadoc-Kommentar mit Beschreibung, Parametern und Rückgabewert.

Angelehnt an: W21 Teil 1, Aufgabe 1bb (Dokumentation) und S24 Teil 1, Aufgabe 1b (Code-Reviews, Dokumentationsrichtlinien)

Aufgabe TQ-07.3 ★★★ Prüfungsniveau 18 Punkte

Wegen des Zeitdrucks vor der Abnahme schlägt der Teamleiter von Brückner Digital vor, die manuellen Code-Reviews abzuschaffen: „Wir haben eine statische Codeanalyse in der CI-Pipeline und eine Testabdeckung von 85 % durch Unit-Tests. Das reicht völlig.“

4 Pa) Beschreiben Sie den Ablauf eines Code-Reviews über einen Pull-Request in vier Schritten.
3 Pb) Nennen Sie drei Vorteile von Code-Reviews.
3 Pc) Nennen Sie zwei Probleme, die eine statische Codeanalyse automatisch findet, und eines, das sie nicht finden kann.
5 Pd) Beurteilen Sie den Vorschlag des Teamleiters.
3 Pe) Als Kompromiss wird vorgeschlagen, für die sicherheitsrelevanten Teile (Zugangsprüfung) Pair Programming einzusetzen. Beschreiben Sie das Verfahren und nennen Sie je einen Vor- und einen Nachteil.

Angelehnt an: W21 Teil 1, Aufgabe 4cb (nur automatische Code-Reviews und Unit-Tests bewerten) und S24 Teil 1, Aufgabe 1b

Originalaufgaben zum Üben

Diese echten Prüfungsaufgaben passen zu diesem Block (Dateien im Ordner Prüfungsvorbereitung). Lösungen gibt es nur für 2023 Sommer, 2023 Winter, 2024 Sommer und 2025 Winter (dort vom u-form-Verlag). Testen fehlte in Winter 2024 ganz; Sommer 2026 fragte nur ISO 25010.

PrüfungAufgabeThemaDatei · Lösung
Winter 2021T1 A1bb (6 P), A3ac (4 P), A4ca (4 P), A4cb (5 P), A4d (4 P)Dokumentation einer Bibliothekserweiterung; Usability-Tests; Effizienz/Änderbarkeit (ISO 25010); „nur automatische Code-Reviews + Unit-Tests“ bewerten; Black-/White-Box2021/winter/AE 2021 Winter Teil 1.pdf · keine Lösung
Winter 2021T2 A1c (6 P)drei Fehler in einem Struktogramm (Passwortprüfung) finden2021/winter/AE 2021 Winter Teil 2.pdf · keine Lösung
Sommer 2022T2 A2 (20 P)Unit-Test beschreiben, Eigenschaften, assertEquals-Testfälle auswerten, Bedingungen korrigieren, Äquivalenzklassen2022/sommer/AE 2022 Sommer Teil 2.pdf · keine Lösung
Winter 2022T2 A2a (11 P)Schreibtischtest einer rekursiven Umwandlung Dezimal → Binär, Fehler korrigieren, Anweisungsüberdeckung/Mindestzahl Testfälle2022/winter/AE 2022 Winter Teil 2.pdf · keine Lösung
Sommer 2023T1 A1e (4 P), A2a (4 P)QS-Maßnahmen; Qualitätsmerkmale nach ISO 91262023/sommer/AE Sommer 2023 Teil 1.pdf · Lösung: AE Sommer 2023 Teil 1+2 Lösungen.pdf
Sommer 2023T2 A3 (25 P)Ticketstatistik (Gruppenwechsel): Datenverlaufstabelle, Fehler nennen, Code korrigieren/erweitern, Anweisungsüberdeckung, Testdaten anpassen2023/sommer/AE Sommer 2023 Teil 2.pdf · Lösung wie oben
Winter 2023T1 A1d (6 P)Inhalte eines Testkonzepts2023/winter/AE Winter 2023 Teil 1.pdf · Lösung: AE Winter 2023 Teil 1 Lösungen.pdf
Sommer 2024T1 A1b (6 P)drei qualitätssichernde Maßnahmen2024/sommer/AE Sommer 2024 Teil 1+2+3.pdf · Lösung: AE Sommer 2024 Teil 1 Lösungen.pdf
Sommer 2024T2 A3 (25 P)Vorteile White-Box, Regressionstest, Anweisungs-/Zweig-/Pfadüberdeckung aus englischem Fachtext, alle Pfade notierenwie oben · Lösung: AE Sommer 2024 Teil 2 Lösungen.pdf
Winter 2025T1 A3ba (3 P), A3bc (6 P)Konformität zur Spezifikation (eRechnung) sicherstellen; warum XSD-Validierung nicht reicht2025/winter/AE Winter 2025 Teil 1.pdf · Lösung: AE Winter 2025 Lösungserleuterungen.pdf (u-form)
Winter 2025T2 A3 (20 P)Unit-Test, Testabdeckung, fehlerhafte Minimum-Funktion: erwartetes/tatsächliches Ergebnis, zwei semantische Fehler korrigieren2025/winter/AE Winter 2025 Teil 2.pdf · Lösung wie oben
Sommer 2026T1 A4a (5 P)ISO 25010: Zuverlässigkeit und ein weiteres Merkmal2026/sommer/AE Sommer 2026 Teil 1.pdf · keine Lösung