java\05_Testen_QS\.
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.
| Unterthema | Kategorie | Typische Punkte | Wichtigste Fähigkeit |
|---|---|---|---|
| TQ-01 Testarten | Meistens | 3–8 je Frage | Teststufen, Black-/White-Box, Regressionstest, Testkonzept |
| TQ-02 Code analysieren, Fehler finden | Meistens | 4–15 | Fehler mit Zeilennummer benennen und korrigieren |
| TQ-03 Unit-Test, Überdeckungsmaße | Oft | 3–12 | assertEquals auswerten, C0/C1/C2, Mindestzahl Testfälle |
| TQ-04 Qualitätsmerkmale ISO/IEC 25010 | Oft | 4–5 | Merkmale beschreiben und auf ein Szenario anwenden |
| TQ-05 Schreibtischtest | Oft | 2–10 | Wertetabelle sauber und vollständig führen |
| TQ-06 Äquivalenzklassen, Testfälle | Wahrscheinlich | 4–10 | gültige/ungültige Klassen, Grenzwerte, Testfalltabelle |
| TQ-07 Codequalität, Reviews | Wahrscheinlich | 5–6 | QS-Maßnahmen erläutern, Code-Review, Clean Code |
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
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.
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.
| Teststufe | Was wird geprüft? | Prüfgrundlage | Wer? Wo? |
|---|---|---|---|
| Komponententest (Unit-, Modultest) | einzelne Methode/Klasse isoliert; Abhängigkeiten werden durch Platzhalter (Stub, Mock) ersetzt | Komponentenspezifikation | Entwickler, Entwicklungsumgebung, automatisiert |
| Integrationstest | Zusammenspiel mehrerer Komponenten, Schnittstellen (z. B. App ↔ REST-API ↔ Datenbank) | technischer Entwurf, Schnittstellenbeschreibung | Entwickler/Tester, Integrationsumgebung |
| Systemtest | das vollständige System gegen alle funktionalen und nicht-funktionalen Anforderungen (Last, Sicherheit, Usability) | Pflichtenheft | unabhängiges Testteam, produktionsnahe Testumgebung |
| Abnahmetest | Erfüllt das System den Vertrag, ist es für den Einsatz beim Kunden geeignet? Ergebnis: Abnahmeprotokoll, ggf. Freigabe | Lastenheft, Vertrag | Auftraggeber 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).
| Statischer Test | Dynamischer Test | |
|---|---|---|
| Prinzip | Prüfobjekt wird nicht ausgeführt, sondern untersucht | Prüfobjekt wird mit Testdaten ausgeführt, Ist- und Soll-Ergebnis werden verglichen |
| Beispiele | Code-Review, Inspektion, Walkthrough, statische Codeanalyse (Linter), Schreibtischtest, Review von Anforderungsdokumenten | Unit-Test, Integrations-, System-, Last-, Abnahmetest |
| Vorteil | schon 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) | |
|---|---|---|
| Grundlage | nur die Spezifikation (Ein-/Ausgabeverhalten); der Code ist unbekannt bzw. wird nicht betrachtet | der Quellcode und seine Kontrollstruktur |
| Verfahren | Äquivalenzklassen, Grenzwertanalyse, Entscheidungstabellen, Zustandsübergänge, Anwendungsfälle | Anweisungs-, Zweig-, Pfad-, Bedingungsüberdeckung |
| Vorteile | prü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 Implementierung | alle 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 |
| Nachteile | keine Aussage, welche Codeteile getestet wurden; unnötiger oder versteckter Code bleibt unentdeckt | fehlende 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).
| Testart | Zweck und Vorgehen |
|---|---|
| Regressionstest | Nach 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-Test | kurzer, 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. |
| Lasttest | Verhalten unter der erwarteten (auch Spitzen-)Last: Antwortzeiten, Durchsatz, Ressourcen. Mit Lastgeneratoren werden viele gleichzeitige Benutzer simuliert (z. B. JMeter, Gatling). |
| Stresstest | Last ü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? |
| Performancetest | Oberbegriff: Antwortzeiten und Ressourcenverbrauch messen (z. B. 95 % der Anfragen unter 1 s). |
| Usability-Test | echte 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). |
| Sicherheitstest | Schwachstellen suchen, z. B. Penetrationstest (simulierter Angriff), Prüfung auf SQL-Injection, Rechteprüfung. |
| Kompatibilitätstest | verschiedene 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.
| Automatisiert | Manuell | |
|---|---|---|
| Stärken | schnell, beliebig oft wiederholbar, gleiche Bedingungen, ideal für Regressionstests und CI | flexibel, findet Unerwartetes (explorativ), beurteilt Bedienbarkeit und Optik |
| Schwächen | Erstellung und Pflege der Skripte kostet Zeit; prüft nur, was programmiert wurde | langsam, teuer bei Wiederholung, fehleranfällig, schlecht reproduzierbar |
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.
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:
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
| Fehlerart | Wann fällt er auf? | Beispiele |
|---|---|---|
| Syntaxfehler | beim Übersetzen (Compiler, IDE markiert rot) – Programm startet gar nicht | fehlendes Semikolon oder Klammer, Schlüsselwort falsch geschrieben, nicht deklarierte Variable, Typfehler (int x = "drei";) |
| Laufzeitfehler | während der Ausführung, meist Programmabbruch mit Exception | Indexü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 finden | falsche 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.
| # | Fehler | Erkennungszeichen und Korrektur |
|---|---|---|
| 1 | Falsche Initialisierung | min := 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). |
| 2 | Off-by-one bei Schleifengrenzen | bis 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). |
| 3 | Falscher Vergleichsoperator | > statt >= bei „mindestens“, „ab“; < statt <= bei „höchstens“, „bis einschließlich“; < und > vertauscht (Minimum ↔ Maximum). |
| 4 | Falscher Divisor / falsche Formel | Durchschnitt 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. |
| 5 | Letzte Gruppe / letztes Element nicht ausgewertet | typisch 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. |
| 6 | Gruppenvariablen nicht zurückgesetzt | beim Gruppenwechsel werden Zähler und Summe zurückgesetzt, aber Minimum/Maximum nicht → Wert „wandert“ in die nächste Gruppe. |
| 7 | Rückgabe an falscher Stelle | rückgabe innerhalb der Schleife → Abbruch nach dem ersten Durchlauf; Rückgabe der falschen Variable (Index statt Wert). |
| 8 | Endlosschleife | in einer solange-Schleife wird die Laufvariable nicht verändert oder in die falsche Richtung; Abbruchbedingung nie erreichbar. |
| 9 | Logische Verknüpfung falsch | und statt oder; Negation falsch umgeformt (De Morgan: nicht (a und b) = nicht a oder nicht b); Klammerung. |
| 10 | Sonderfall nicht behandelt | null, leeres Array/leere Liste, ein einziges Element, alle Werte gleich, negative Werte – Spezifikation genau lesen, was dann passieren soll (Exception? 0? leere Liste?). |
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.
| Zeile | Fehler (Ursache → Auswirkung) | Korrektur |
|---|---|---|
| 02 | Startwert 0 ist kein Messwert → bei nur negativen Werten wird 0 geliefert | max : double := werte[0] |
| 03 | Endwert werte.length ist kein gültiger Index → Laufzeitfehler im letzten Durchlauf | zähle i von 1 bis werte.length - 1 (oder von 0) |
| 07 | rückgabe innerhalb der Schleife → nur das erste Element wird ausgewertet | Zeile 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.
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)?
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.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.Vorkommen: 5/9 · Prüfungen: S22, W22, S23, S24, W25 · fast immer Teil 2, oft als Teil einer 20–25-Punkte-Testaufgabe
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 – schnell | läuft in Millisekunden, damit man tausende Tests bei jeder Änderung ausführen kann |
| Independent/Isolated – unabhängig | hängt nicht von anderen Tests, ihrer Reihenfolge, einer echten Datenbank, dem Netz oder der Uhrzeit ab; Abhängigkeiten werden durch Stubs/Mocks ersetzt |
| Repeatable – wiederholbar | liefert bei jeder Ausführung und auf jedem Rechner dasselbe Ergebnis (deterministisch) |
| Self-validating – selbstprüfend | entscheidet selbst über bestanden/fehlgeschlagen (Assertion), niemand muss Ausgaben ansehen |
| Timely – zeitnah | wird 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).
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 |
|---|---|
@Test | markiert eine Testmethode |
@BeforeEach | Methode 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 |
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.
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
versandkosten| Maß | Forderung | Beispiel 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) |
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.
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.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.
sonst entstehen. · „Mindestanzahl“ immer mit kurzer Begründung bzw. konkreten Testdaten angeben.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.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:
| Merkmal | Untermerkmale | Leitfrage | Beispiel (Online-Banking-App) |
|---|---|---|---|
| Funktionale Eignung (functional suitability) | funktionale Vollständigkeit, Korrektheit, Angemessenheit | Tut 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ät | Wie schnell und sparsam? | Kontostand erscheint in < 2 s; die App braucht < 150 MB Speicher; 20 000 gleichzeitige Nutzer. |
| Kompatibilität (compatibility) | Koexistenz, Interoperabilität | Arbeitet 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, Wiederherstellbarkeit | Funktioniert 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ät | Sind 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, Austauschbarkeit | Lä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.
| ISO/IEC 9126 (6 Merkmale) | Untermerkmale 9126 | wird in ISO/IEC 25010 (2011) zu … |
|---|---|---|
| Funktionalität | Angemessenheit, Richtigkeit, Interoperabilität, Sicherheit, Ordnungsmäßigkeit | Funktionale Eignung; Sicherheit wird eigenes Merkmal; Interoperabilität wandert zur neuen Kompatibilität |
| Zuverlässigkeit | Reife, Fehlertoleranz, Wiederherstellbarkeit | Zuverlässigkeit (+ Verfügbarkeit) |
| Benutzbarkeit | Verständlichkeit, Erlernbarkeit, Bedienbarkeit, Attraktivität | Benutzbarkeit (+ Schutz vor Fehlbedienung, Zugänglichkeit) |
| Effizienz | Zeitverhalten, Verbrauchsverhalten | Leistungseffizienz (+ Kapazität) |
| Änderbarkeit | Analysierbarkeit, Modifizierbarkeit, Stabilität, Prüfbarkeit | Wartbarkeit (+ Modularität, Wiederverwendbarkeit) |
| Übertragbarkeit | Anpassbarkeit, 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.
„Die App soll schnell und zuverlässig sein“ ist nicht prüfbar. Eine Qualitätsanforderung braucht eine Messgröße, einen Zielwert und Messbedingungen:
| Merkmal | Messgröße | messbare Formulierung (Beispiel Online-Banking) |
|---|---|---|
| Leistungseffizienz | Antwortzeit (Perzentil), Durchsatz, Speicher-/CPU-Bedarf | „Bei 5 000 gleichzeitigen Nutzern werden 95 % der Kontoabfragen in höchstens 2 s beantwortet.“ |
| Zuverlässigkeit | Verfü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.“ |
| Benutzbarkeit | Zeit/Fehlerquote/Erfolgsquote bei Aufgaben, Zufriedenheitswert (Fragebogen) | „8 von 10 Erstnutzern führen ohne Hilfe eine Überweisung in höchstens 3 Minuten aus.“ |
| Wartbarkeit | Zweigüberdeckung der Unit-Tests, zyklomatische Komplexität je Methode, Aufwand für Änderungen | „Zweigüberdeckung mindestens 80 %; keine Methode mit Komplexität über 10.“ |
| Sicherheit | Befunde im Penetrationstest, Verschlüsselungsstandard, Sperrregeln | „Nach 3 falschen PIN-Eingaben wird der Zugang 30 min gesperrt; keine kritischen Befunde im Penetrationstest.“ |
| Übertragbarkeit | unterstü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).
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.
zähle: ist der Endwert erreicht?). Die Laufvariable ändert sich erst am Ende des Durchlaufs.7 div 2 = 3, 7 mod 2 = 1, in Java 7 / 2 = 3).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
| i | werte[i-1] | werte[i] | Z. 04 | anzahl |
|---|---|---|---|---|
| – | – | – | – | 0 |
| 1 | 3 | 5 | wahr | 1 |
| 2 | 5 | 5 | falsch | 1 |
| 3 | 5 | 8 | wahr | 2 |
| 4 | 8 | 2 | falsch | 2 |
| 5 | 2 | 4 | wahr | 3 |
Rückgabe: 3. Dieselbe Rechnung als Datenverlaufstabelle:
| Typ | Variable | Werteverlauf |
|---|---|---|
| integer | i | 1, 2, 3, 4, 5 |
| integer | anzahl | 0, 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
| i | j | summe |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 0 | 2 | 3 |
| 1 | 1 | 4 |
| 1 | 2 | 6 |
| 2 | 2 | 8 |
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).
| Aufruf | a | b | b = 0? | a mod b | Rückgabe |
|---|---|---|---|---|---|
| 1 | 84 | 36 | nein | 12 | Ergebnis von Aufruf 2 = 12 |
| 2 | 36 | 12 | nein | 0 | Ergebnis von Aufruf 3 = 12 |
| 3 | 12 | 0 | ja (Basisfall) | – | 12 |
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).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.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:
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.
null → je eine ungültige Klasse.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.
| Nr. | Äquivalenzklasse | Repräsentant | erwartetes Ergebnis |
|---|---|---|---|
| ÄK1 | gültig: 92–100 | 95 | 1 |
| ÄK2 … ÄK6 | gültig: 81–91, 67–80, 50–66, 30–49, 0–29 | 85, 70, 60, 40, 10 | 2, 3, 4, 5, 6 |
| ÄK7 | ungültig: < 0 | −5 | Fehlermeldung |
| ÄK8 | ungültig: > 100 | 120 | Fehlermeldung |
| ÄK9 | ungü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. | gewichtKg | land | abgedeckte Klassen | erwartet |
|---|---|---|---|---|
| 1 | 1,5 | „DE“ | Gewicht Stufe 1, DE | Preis Stufe 1 DE |
| 2 | 5,0 | „AT“ | Gewicht Stufe 2, AT | Preis Stufe 2 AT |
| 3 | 20,0 | „CH“ | Gewicht Stufe 3, CH | Preis Stufe 3 CH |
| 4 | 0,0 | „DE“ | ungültig: Gewicht ≤ 0 | Fehler |
| 5 | 40,0 | „DE“ | ungültig: Gewicht > 31,5 | Fehler |
| 6 | 5,0 | „FR“ | ungültig: anderes Land | Fehler |
| 7 | 5,0 | null | ungültig: Land fehlt | Fehler |
null, leeres Array/leere Liste/leerer Text, genau ein Element, alle Werte gleich, Maximum am Anfang oder Ende, negative Werte, sehr große Werte, Sonderzeichen und Umlaute.null) auswerten.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
| Konstruktive QS (Fehler vermeiden) | Analytische QS (Fehler finden) | |
|---|---|---|
| Idee | Rahmenbedingungen so setzen, dass Fehler gar nicht erst entstehen | vorhandene Ergebnisse prüfen und bewerten |
| Beispiele | definiertes 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, TDD | Code-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“).
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.
| Reviewart | Merkmale (vom informellsten zum formalsten) |
|---|---|
| Informelles Review | Kollege schaut drüber („Schulterblick“), keine Dokumentation |
| Walkthrough | Autor stellt den Code vor und führt durch, Teilnehmer stellen Fragen; dient auch dem Wissenstransfer |
| Technisches Review | Fachleute prüfen gegen Vorgaben/Checkliste, Ergebnisse werden protokolliert, Entscheidung über Freigabe |
| Inspektion | formalstes Verfahren mit Rollen (Moderator, Autor, Gutachter, Protokollant), Checklisten, Metriken und Nachkontrolle |
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.
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.
PascalCase (Kunde), Methoden und Variablen camelCase (berechneSumme, anzahlKunden), Konstanten UPPER_SNAKE_CASE (MAX_VERSUCHE), Pakete klein. Methoden mit Verb, boolesche Methoden mit ist…/hat….ifs, eine Anweisung pro Zeile, begrenzte Zeilenlänge.@param (Parameter), @return (Rückgabewert), @throws (ausgelöste Exception), @author, @version, @since, @see, @deprecated./**
* 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) { … }
| Regel | Bedeutung |
|---|---|
| Sprechende Namen | Name 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, YAGNI | so einfach wie möglich; nichts „auf Vorrat“ programmieren. |
| Flache Verschachtelung | Sonderfälle früh abfangen (Guard Clause) statt tief verschachtelter ifs. |
| Wenige Parameter, keine Seiteneffekte | eine Methode berechne… rechnet nur und ändert nicht nebenbei Daten. |
| Fehlerbehandlung mit Exceptions | statt geheimer Rückgabecodes; Fehler nicht stillschweigend verschlucken. |
| Pfadfinderregel | Code 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.
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.
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 | Beschreibung |
|---|---|
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.
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:
| Methode | Spezifikation |
|---|---|
| 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[]) : integer | trainiert[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) : double | siehe Anlage 3 (Beitragsordnung) und Anlage 4 (Listing) |
| bonuspunkte(minuten : integer[]) : integer | siehe Anlage 3 (Bonusprogramm) |
| kursStatistik(termine : List<Termin>) | siehe Anlage 5 |
| zugangPruefen(m : Mitglied, bereich : string) : string | siehe Anlage 6 |
| Tarif | Monatsbeitrag | Leistungen |
|---|---|---|
| „BASIC“ | 29,90 € | Trainingsbereich, Kurse |
| „PREMIUM“ | 49,90 € | zusätzlich Sauna und Getränke |
| Alter (in vollen Jahren) | Ermäßigung |
|---|---|
| 14 bis 17 Jahre | 50 % |
| 18 bis 64 Jahre | keine |
| ab 65 Jahre | 20 % |
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.
| Leistung | Preis |
|---|---|
| Tageskarte | 15,00 € je Karte |
| Tageskarte ermäßigt (Schüler, Studierende) | 10,00 € je Karte |
| Mengenrabatt ab 10 gleichzeitig gekauften Karten | 10 % auf den Kartenpreis |
| Sauna-Zuschlag | 5,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.
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 }
kursStatistik mit TestdatenDie 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
| Index | kurs | datum | teilnehmer |
|---|---|---|---|
| 0 | Aqua-Fitness | 03.11.2026 | 14 |
| 1 | Aqua-Fitness | 10.11.2026 | 18 |
| 2 | Rückenfit | 04.11.2026 | 10 |
| 3 | Rückenfit | 11.11.2026 | 12 |
| 4 | Rückenfit | 18.11.2026 | 8 |
| 5 | Yoga | 05.11.2026 | 16 |
| 6 | Yoga | 12.11.2026 | 13 |
Erwartete Ausgabe für diese Testdaten:
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 }
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.
| Anweisung | Beschreibung |
|---|---|
| @Test | kennzeichnet 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.*;
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.
Im Projekt VitaPark Connect werden Tests auf verschiedenen Stufen durchgeführt.
| Nr. | Situation | Teststufe | Prüfgrundlage |
|---|---|---|---|
| 1 | Eine Entwicklerin prüft die Methode beitrag (Anlage 4) isoliert mit eigenen Testdaten, bevor sie den Code in das gemeinsame Repository übernimmt. | ||
| 2 | Es 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. | ||
| 3 | Die Testerin prüft das vollständig installierte System in einer produktionsnahen Testumgebung gegen alle Anforderungen des Pflichtenhefts, einschließlich der Antwortzeiten. | ||
| 4 | Die Geschäftsführung der VitaPark Fitness GmbH spielt am 15.02.2027 typische Abläufe aus dem Studioalltag durch und entscheidet über die Freigabe. |
Angelehnt an: W23 Teil 1, Aufgabe 1d (Zusammenspiel der Teststufen) und W21 Teil 1, Aufgabe 4
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.Angelehnt an: S24 Teil 2, Aufgabe 3a (Vorteile White-Box, Regressionstest) und W21 Teil 1, Aufgabe 4d
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.
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)
| Nr. | Fehler | Syntaxfehler | Laufzeitfehler | Logikfehler |
|---|---|---|---|---|
| 1 | In der Zeile int anzahl = 0 fehlt das Semikolon. | |||
| 2 | In einer Schleife wird auf puls[puls.length] zugegriffen. | |||
| 3 | Die Summe der Teilnehmer wird mit summe = summe - t.getTeilnehmer() gebildet. | |||
| 4 | Ein Rabatt von 20 % wird als preis * 0.2 statt preis * 0.8 berechnet. | |||
| 5 | Statt return wurde retrun geschrieben. | |||
| 6 | Eine Methode erhält null statt einer Liste und ruft termine.size() auf. |
Angelehnt an: W25 Teil 2, Aufgabe 3bb (semantische Fehler)
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 }
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.| i | puls[i] | Bedingung Zeile 05 | summe | anzahl |
|---|---|---|---|---|
Angelehnt an: W25 Teil 2, Aufgabe 3b (fehlerhafte Funktion durchspielen und korrigieren)
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.
| Typ | Variable | Werteverlauf |
|---|---|---|
| integer | i | |
| string | kurs | |
| integer | anzahl | |
| integer | summe | |
| integer | max | |
| integer | anzahlGesamt | |
| integer | summeGesamt |
Tatsächliche Ausgabe:
Angelehnt an: S23 Teil 2, Aufgabe 3a (Jahresstatistik mit Datenverlaufstabelle, Fehler nennen, Code korrigieren und erweitern)
Die Methoden der Klasse Kurs (Anlage 2) sollen mit Unit-Tests geprüft werden.
@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
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
}
| Testfall | Rückgabewert der Methode | Ergebnis des Tests (OK / Fehler) |
|---|---|---|
| 1 | ||
| 2 | ||
| 3 | ||
| 4 | ||
| 5 | ||
| 6 |
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)
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).
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).| Nummer | Pfad |
|---|---|
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 |
zugangPruefen.Angelehnt an: S24 Teil 2, Aufgabe 3b/3c (Überdeckungsmaße aus englischem Fachtext, alle Pfade notieren) und W22 Teil 2, Aufgabe 2ac
Im Pflichtenheft von VitaPark Connect stehen unter anderem die folgenden nicht-funktionalen Anforderungen.
| Nr. | Anforderung | Qualitätsmerkmal |
|---|---|---|
| 1 | Die Auslastungsanzeige der App wird nach dem Antippen in höchstens 2 Sekunden aktualisiert. | |
| 2 | Fällt die Verbindung zum Server aus, kann das Drehkreuz die Mitgliedskarten der letzten 24 Stunden weiterhin offline prüfen. | |
| 3 | Neue Trainer können nach einer 15-minütigen Einweisung selbstständig Kurse anlegen. | |
| 4 | Trainingsdaten können von Fitnessarmbändern verschiedener Hersteller übernommen werden. | |
| 5 | Ein neuer Tarif kann ergänzt werden, indem nur das Modul „Beitragsberechnung“ geändert wird. | |
| 6 | Pulsdaten 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
Angelehnt an: S26 Teil 1, Aufgabe 4a (Zuverlässigkeit) und W21 Teil 1, Aufgabe 4ca (Effizienz, Änderbarkeit)
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.
| Merkmal | konkrete Anforderung | messbares Abnahmekriterium | Prüfung |
|---|---|---|---|
| Zuverlässigkeit | |||
| Leistungseffizienz | |||
| Sicherheit |
Angelehnt an: S23 Teil 1, Aufgabe 2a (Qualitätsmerkmale nach ISO 9126) und S26 Teil 1, Aufgabe 4a
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
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.| i | minuten[i] | Bedingung Zeile 04 | Bedingung Zeile 07 | punkte |
|---|---|---|---|---|
| – | – | – | – | 0 |
Angelehnt an: W22 Teil 2, Aufgabe 2aa und S23 Teil 2, Aufgabe 3a (Schreibtischtest)
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
| tag | std 0 (17 Uhr) | std 1 (18 Uhr) | std 2 (19 Uhr) | std 3 (20 Uhr) |
|---|---|---|---|---|
| 0 (Mo) | 40 | 85 | 90 | 95 |
| 1 (Di) | 70 | 82 | 60 | 88 |
| 2 (Mi) | 91 | 50 | 96 | 97 |
| tag | std | besucher[tag][std] | Bedingung Zeile 06 | folge | anzahl |
|---|---|---|---|---|---|
| – | – | – | – | 0 | 0 |
Angelehnt an: S23 Teil 2, Aufgabe 3a (Schreibtischtest über verschachtelte Daten, Fehler finden)
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 }
true, F = false). Tragen Sie das laut Spezifikation erwartete und das tatsächliche Ergebnis ein.| TF | Testdaten trainiert | erwartetes Ergebnis | tatsä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) | ||
| 6 | null |
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
| Aufruf | i | i >= t.length | t[i] | Rückgabewert |
|---|---|---|---|---|
| 1 | ||||
| 2 | ||||
| 3 | ||||
| 4 | ||||
| 5 |
laengsteSerie mit Zeilennummer und korrigieren Sie die Methode.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
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.
| ÄK | gültig / ungültig | Beschreibung | Repräsentant |
|---|---|---|---|
| 1 | |||
| 2 | |||
| 3 | |||
| 4 |
Angelehnt an: S22 Teil 2, Aufgabe 2bc (Testdaten aus Äquivalenzklassen)
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.
| Parameter | gültige Äquivalenzklassen | ungültige Äquivalenzklassen |
|---|---|---|
| alter | ||
| tarif |
| Nr. | alter | tarif | abgedeckte Äquivalenzklassen | erwartetes Ergebnis |
|---|---|---|---|---|
| 1 | ||||
| 2 | ||||
| 3 | ||||
| 4 | ||||
| 5 | ||||
| 6 | ||||
| 7 | ||||
| 8 |
alter ergeben (Tarif jeweils „BASIC“), mit dem erwarteten Ergebnis.| alter | erwartetes Ergebnis | alter | erwartetes Ergebnis |
|---|---|---|---|
Angelehnt an: S22 Teil 2, Aufgabe 2bc (Äquivalenzklassen) und W25 Teil 2, Aufgabe 3ba (Testdaten mit Sonderfällen)
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:
| TF | alter | tarif | erwartetes Ergebnis |
|---|---|---|---|
| TF1 | 16 | „PREMIUM“ | 24.95 |
| TF2 | 40 | „BASIC“ | 29.90 |
| TF3 | 65 | „BASIC“ | 23.92 |
| TF4 | 13 | „BASIC“ | IllegalArgumentException |
| TF5 | 30 | „GOLD“ | IllegalArgumentException |
| TF6 | 30 | null | IllegalArgumentException |
Angelehnt an: S22 Teil 2, Aufgabe 2b (Unit-Test, Bedingungen korrigieren, Äquivalenzklassen) und S23 Teil 2, Aufgabe 3bc (Testdaten für volle Anweisungsüberdeckung)
Die Geschäftsführung der VitaPark Fitness GmbH fragt, wie Brückner Digital die Qualität der Software schon während der Entwicklung sicherstellt.
Angelehnt an: S24 Teil 1, Aufgabe 1b und S23 Teil 1, Aufgabe 1e
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 }
Angelehnt an: W21 Teil 1, Aufgabe 1bb (Dokumentation) und S24 Teil 1, Aufgabe 1b (Code-Reviews, Dokumentationsrichtlinien)
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.“
Angelehnt an: W21 Teil 1, Aufgabe 4cb (nur automatische Code-Reviews und Unit-Tests bewerten) und S24 Teil 1, Aufgabe 1b
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üfung | Aufgabe | Thema | Datei · Lösung |
|---|---|---|---|
| Winter 2021 | T1 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-Box | 2021/winter/AE 2021 Winter Teil 1.pdf · keine Lösung |
| Winter 2021 | T2 A1c (6 P) | drei Fehler in einem Struktogramm (Passwortprüfung) finden | 2021/winter/AE 2021 Winter Teil 2.pdf · keine Lösung |
| Sommer 2022 | T2 A2 (20 P) | Unit-Test beschreiben, Eigenschaften, assertEquals-Testfälle auswerten, Bedingungen korrigieren, Äquivalenzklassen | 2022/sommer/AE 2022 Sommer Teil 2.pdf · keine Lösung |
| Winter 2022 | T2 A2a (11 P) | Schreibtischtest einer rekursiven Umwandlung Dezimal → Binär, Fehler korrigieren, Anweisungsüberdeckung/Mindestzahl Testfälle | 2022/winter/AE 2022 Winter Teil 2.pdf · keine Lösung |
| Sommer 2023 | T1 A1e (4 P), A2a (4 P) | QS-Maßnahmen; Qualitätsmerkmale nach ISO 9126 | 2023/sommer/AE Sommer 2023 Teil 1.pdf · Lösung: AE Sommer 2023 Teil 1+2 Lösungen.pdf |
| Sommer 2023 | T2 A3 (25 P) | Ticketstatistik (Gruppenwechsel): Datenverlaufstabelle, Fehler nennen, Code korrigieren/erweitern, Anweisungsüberdeckung, Testdaten anpassen | 2023/sommer/AE Sommer 2023 Teil 2.pdf · Lösung wie oben |
| Winter 2023 | T1 A1d (6 P) | Inhalte eines Testkonzepts | 2023/winter/AE Winter 2023 Teil 1.pdf · Lösung: AE Winter 2023 Teil 1 Lösungen.pdf |
| Sommer 2024 | T1 A1b (6 P) | drei qualitätssichernde Maßnahmen | 2024/sommer/AE Sommer 2024 Teil 1+2+3.pdf · Lösung: AE Sommer 2024 Teil 1 Lösungen.pdf |
| Sommer 2024 | T2 A3 (25 P) | Vorteile White-Box, Regressionstest, Anweisungs-/Zweig-/Pfadüberdeckung aus englischem Fachtext, alle Pfade notieren | wie oben · Lösung: AE Sommer 2024 Teil 2 Lösungen.pdf |
| Winter 2025 | T1 A3ba (3 P), A3bc (6 P) | Konformität zur Spezifikation (eRechnung) sicherstellen; warum XSD-Validierung nicht reicht | 2025/winter/AE Winter 2025 Teil 1.pdf · Lösung: AE Winter 2025 Lösungserleuterungen.pdf (u-form) |
| Winter 2025 | T2 A3 (20 P) | Unit-Test, Testabdeckung, fehlerhafte Minimum-Funktion: erwartetes/tatsächliches Ergebnis, zwei semantische Fehler korrigieren | 2025/winter/AE Winter 2025 Teil 2.pdf · Lösung wie oben |
| Sommer 2026 | T1 A4a (5 P) | ISO 25010: Zuverlässigkeit und ein weiteres Merkmal | 2026/sommer/AE Sommer 2026 Teil 1.pdf · keine Lösung |