Updated Modultestplan

main
Lucas Strubel 2026-06-15 16:04:17 +02:00
parent 4789cbabf1
commit 77e3ec2a33
3 changed files with 211 additions and 77 deletions

View File

@ -1,9 +1,9 @@
---
title: "Modultestplan"
subtitle: "Desktop-Fakturierungsanwendung — Gruppe A: Prozess / Dokumentenzyklus"
subtitle: "Desktop-Fakturierungsanwendung — Gesamtsystem (alle Komponenten)"
author:
- Team 1 Gruppe A
version: "1.0"
- Team 1
version: "2.0"
lang: de-DE
toc: true
toc-depth: 3
@ -20,12 +20,19 @@ header-includes: |
\usepackage{lastpage}
\pagestyle{fancy}
\fancyhf{}
\fancyhead[L]{Team 1 Gruppe A}
\fancyhead[L]{Team 1}
\fancyhead[C]{Modultestplan}
\fancyhead[R]{Version 1.0}
\fancyhead[R]{Version 2.0}
\fancyfoot[C]{\thepage\ /\ \pageref{LastPage}}
\renewcommand{\headrulewidth}{0.4pt}
\renewcommand{\footrulewidth}{0pt}
\makeatletter
\def\brk@scan#1{\ifx\brk@end#1\else#1\allowbreak\expandafter\brk@scan\fi}
\newcommand{\brk}[1]{\brk@scan#1\brk@end}
\let\origtexttt\texttt
\renewcommand{\texttt}[1]{\origtexttt{\brk{#1}}}
\makeatother
\AtBeginEnvironment{longtable}{\small}
---
\newpage
@ -35,103 +42,230 @@ header-includes: |
+=========================+=========================+=========================+
| Strubel, Lucas | Prof. Dr. Marmitt, Gerd | Prof. Dr. Marmitt, Gerd |
+-------------------------+-------------------------+-------------------------+
| Gruppe A (Prozess) | Modulverantwortlicher | Modulverantwortlicher |
| Team 1 (Gesamtsystem) | Modulverantwortlicher | Modulverantwortlicher |
+-------------------------+-------------------------+-------------------------+
| 15.06.2026 | 15.06.2026 | 15.06.2026 |
+-------------------------+-------------------------+-------------------------+
**Freigabevermerk:** Dieses Dokument ist nach Prüfung und Freigabe durch den
Modulverantwortlichen verbindliche Grundlage für den Modultest der Komponente
*Prozess / Dokumentenzyklus*.
Modulverantwortlichen verbindliche Grundlage für den Modultest des Gesamtsystems
*Desktop-Fakturierungsanwendung* (Komponenten AD, gemeinsame Infrastruktur sowie
Performance-Nachweise).
## Dokumentenhistorie
| Version | Datum | Autor | Grund der Änderung |
|---------|------------|-----------------------------|---------------------|
| 1.0 | 15.06.2026 | Lucas Strubel | Initiale Erstellung (ausgegliedert aus Pflichtenheft Gruppe A v1.2) |
| 2.0 | 15.06.2026 | Lucas Strubel | Konsolidierung aller Komponenten-Testfälle (AD, gemeinsame Infrastruktur, Performance) in einen projektweiten Modultestplan |
\newpage
## 1. Einleitung
### 1.1 Zweck des Dokuments
Dieser Modultestplan spezifiziert die Modul-/Komponententests der Komponente
*Prozess / Dokumentenzyklus* (Gruppe A). Er leitet sich direkt aus dem Pflichtenheft
Gruppe A (ab Version 1.2) ab — insbesondere aus den funktionalen Anforderungen (Kapitel 4),
den Daten und Schnittstellen (Kapitel 6) sowie den testbaren Abnahmekriterien (Kapitel 8) —
und überführt diese in deterministische, mit JUnit umsetzbare Testfälle.
Dieser Modultestplan spezifiziert die Modul-/Komponententests des **Gesamtsystems**
*Desktop-Fakturierungsanwendung*. Er fasst die Testfälle aller vier Komponenten
(A Prozess/Dokumentenzyklus, B Produktverwaltung, C Kundenverwaltung,
D Programmoberfläche), der gemeinsam genutzten Infrastruktur (Paket `gemeinsam`) sowie
die übergreifenden Performance-/Lastnachweise in einem Dokument zusammen. Die Testfälle
leiten sich aus den funktionalen Anforderungen, Daten/Schnittstellen und testbaren
Abnahmekriterien der jeweiligen Pflichtenhefte ab und überführen diese in deterministische,
mit JUnit 5 umgesetzte Testfälle. Quelle der Wahrheit sind die Testklassen unter
`src/test/java/de/team1/faktura/…`.
### 1.2 Rahmenbedingungen
Die folgenden Testfälle sind deterministisch (feste Ein-/Ausgaben) und mit JUnit 5
umsetzbar. Geldbeträge werden als `BigDecimal` mit Scale 2 erwartet
(`assertEquals(new BigDecimal("119.00"), …)` bzw. `compareTo`). Die Schnittstellen der
Gruppen B (Produkte) und C (Kunden) sowie der PDF-Export werden in den Tests durch Stubs
ersetzt.
umgesetzt. Geldbeträge werden als `java.math.BigDecimal` mit **Scale 2** erwartet
(`assertEquals(new BigDecimal("119.00"), …)` bzw. `compareTo`). Die jeweils benachbarten
Komponenten werden im Modultest durch **Stubs/Mocks** ersetzt:
- **Komponente A** ersetzt die Schnittstellen der Gruppen B (Produkte) und C (Kunden) sowie
den PDF-Export durch Stubs.
- **Komponente B** ersetzt die Schnittstelle `ProduktReferenzPruefung` (Gruppe A) durch einen Stub.
- **Komponente C** ersetzt die Schnittstelle `KundenReferenzPruefung` (Gruppe A) durch einen Stub.
- **Komponente D** ersetzt die Service-Schnittstellen der Gruppen AC durch Stubs/Mocks.
Die Abkürzungen für die abgedeckten Pflichtenheft-Anforderungen (Spalte *Abgedeckte
PH-Anf.*) sind **komponentenlokal** zu lesen: `F-01` in Abschnitt 2.2 bezeichnet eine
Anforderung des Pflichtenhefts B, nicht des Pflichtenhefts A.
## 2. Testfälle
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
### 2.1 Komponente A — Prozess / Dokumentenzyklus
#### 2.1.1 Dokumentenzyklus (`DokumentzyklusTest`)
| TC | Abgedeckte PH-Anf. | Vorbedingung | Eingabe | Erwartetes Ergebnis |
+=======+====================+=============================+===========================+=============================+
| TC-01 | F-23, F-03 | Position mit Netto 100.00 | `berechne()` | Steuer = 19.00, Brutto = |
| | | €, Steuersatz 0.19 | | 119.00 (Scale 2) |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-02 | F-23 | Einzelpreis 50.00 €, | Positionssumme | positionssummeNetto = |
| | | Menge 3 | berechnen | 150.00 |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-03 | F-03, F-13 | Beleg mit 2 Positionen | Summen berechnen | summeNetto = 200.00, |
| | | (150.00 € @ 0.19; | | summeSteuer = 32.00, |
| | | 50.00 € @ 0.07) | | summeBrutto = 232.00 |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-04 | F-12, GR-01 | Letzte Rechnungsnummer | `naechsteNummer` | liefert `R-2026-000124` |
| | | `R-2026-000123` | `(RECHNUNG, 2026)` | (lückenlos) |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-05 | F-12 (Format) | Zähler = 7, Jahr 2026 | `naechsteNummer` | liefert `R-2026-000007` |
| | | | `(RECHNUNG, 2026)` | (führende Nullen, `String`) |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-06 | F-14, GR-06 | Rechnungsdatum 2026-06-09, | Rechnung erstellen | zahlungsziel = |
| | | kein Zahlungsziel | | 2026-06-23 (+14 Tage) |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-07 | F-14 | Rechnungsdatum 2026-06-09, | Rechnung erstellen | zahlungsziel = 2026-07-31 |
| | | Zahlungsziel 2026-07-31 | | (übernommen) |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-08 | F-24, NF-INT-01 | Rechnung im Status | `setzePosition(...)` / | wirft |
| | | `VERSENDET` | Änderung | `IllegalStateException` |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-09 | F-19, F-20 | Rechnung im Status `OFFEN` | `storniere()` | Status = `STORNIERT`; |
| | | | | nicht in |
| | | | | `offeneRechnungen()`; |
| | | | | `storniertAm` gesetzt |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-10 | F-22, GR-05 | Angebot `AN-2026-000001` | `ausAngebot(angebot)` | AB übernimmt Kunde/ |
| | | mit Kunde + 2 Positionen | (AB erzeugen) | Positionen/Mengen; |
| | | | | `vorgaengerNr` = |
| | | | | `"AN-2026-000001"` |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-11 | F-23, F-24 | Rechnung mit Produkt @ | erste Rechnung erneut | einzelpreisNetto bleibt |
| | | 50.00 €; danach | lesen | 50.00 (Snapshot |
| | | Produktpreis → 80.00 € | | unverändert) |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-12 | F-18, NF-USE-02 | Rechnung ohne Kunde | `speichere()` | Speichern abgelehnt; |
| | | **oder** ohne Position | | Validierungsfehler benennt |
| | | | | fehlendes Pflichtfeld |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
| TC-13 | F-11, F-12, F-13 | Kunde + 1 Position | vollständige Rechnung | Rechnung gespeichert, |
| | | vorhanden | erstellen | Nummer vergeben, alle |
| | | | | § 14 UStG-Pflichtangaben |
| | | | | gesetzt |
+-------+--------------------+-----------------------------+---------------------------+-----------------------------+
|---------|------------|------------------------|----------------------|----------------------------|
| TC-01 | F-23, F-03 | Position mit Netto 100.00 €, Steuersatz 0.19 | `berechne()` | Steuer = 19.00, Brutto = 119.00 (Scale 2) |
| TC-02 | F-23 | Einzelpreis 50.00 €, Menge 3 | Positionssumme berechnen | positionssummeNetto = 150.00 |
| TC-03 | F-03, F-13 | Beleg mit 2 Positionen (150.00 € @ 0.19; 50.00 € @ 0.07) | Summen berechnen | summeNetto = 200.00, summeSteuer = 32.00, summeBrutto = 232.00 |
| TC-04 | F-12, GR-01 | Letzte Rechnungsnummer `R-2026-000123` | `naechsteNummer(RECHNUNG, 2026)` | liefert `R-2026-000124` (lückenlos) |
| TC-05 | F-12 (Format) | Zähler = 7, Jahr 2026 | `naechsteNummer(RECHNUNG, 2026)` | liefert `R-2026-000007` (führende Nullen, `String`) |
| TC-06 | F-14, GR-06 | Rechnungsdatum 2026-06-09, kein Zahlungsziel | Rechnung erstellen | zahlungsziel = 2026-06-23 (+14 Tage) |
| TC-07 | F-14 | Rechnungsdatum 2026-06-09, Zahlungsziel 2026-07-31 | Rechnung erstellen | zahlungsziel = 2026-07-31 (übernommen) |
| TC-08 | F-24, NF-INT-01 | Rechnung im Status `VERSENDET` | `setzePositionen(...)` / Änderung | wirft `IllegalStateException` |
| TC-09 | F-19, F-20 | Rechnung im Status `OFFEN` | `storniere()` | Status = `STORNIERT`; nicht in `offeneRechnungen()`; `storniertAm` und `storniertVon` gesetzt |
| TC-10 | F-22, GR-05 | Angebot `AN-2026-000001` mit Kunde + 2 Positionen | `erzeugeFolgebeleg(angebot)` (AB erzeugen) | AB übernimmt Kunde/Positionen/Mengen; `vorgaengerNr` = `"AN-2026-000001"` |
| TC-11 | F-23, F-24 | Rechnung mit Produkt @ 50.00 €; danach Produktpreis → 80.00 € | erste Rechnung erneut lesen | einzelpreisNetto bleibt 50.00 (Snapshot unverändert) |
| TC-12 | F-18, NF-USE-02 | Rechnung ohne Kunde **oder** ohne Position | `erstelleRechnung(...)` | Speichern abgelehnt; Validierungsfehler benennt fehlendes Pflichtfeld (`Kunde` bzw. `Position`) |
| TC-13 | F-11, F-12, F-13 | Kunde + 1 Position vorhanden | vollständige Rechnung erstellen | Rechnung gespeichert, Nummer `R-2026-…` vergeben, alle § 14 UStG-Pflichtangaben gesetzt |
Damit sind 13 Testfälle (> 10) spezifiziert, die alle funktionalen Kernregeln (F-12, F-14,
F-18, F-22, F-23, F-24) sowie die zentralen Geschäftsregeln (GR-01, GR-02, GR-03, GR-05,
GR-06) abdecken.
#### 2.1.2 Belegpersistenz (`JsonDokumentRepositoryTest`)
## 3. Abkürzungen
| TC | Abgedeckte PH-Anf. | Vorbedingung | Eingabe | Erwartetes Ergebnis |
|---------|------------|------------------------|----------------------|----------------------------|
| TC-14 | IF-01 (GoBD) | Repository mit gespeicherter Rechnung `R-2026-000001` (OFFEN) und Angebot `AN-2026-000001` (ENTWURF) | Repository neu instanziieren (Neustart) | beide Belege geladen (`alle().size() == 2`); polymorphe Typen `Rechnung`/`Angebot` bleiben erhalten; Positionen ≠ `null` |
#### 2.1.3 PDF-Export (`PdfBoxPdfExporterTest`)
| TC | Abgedeckte PH-Anf. | Vorbedingung | Eingabe | Erwartetes Ergebnis |
|---------|------------|------------------------|----------------------|----------------------------|
| TC-15 | F-15, IF-01 | Vollständige Rechnung `R-2026-000001` | `exportiere(rechnung, ziel)` | PDF-Datei existiert am Zielpfad |
| TC-16 | F-15 (Robustheit) | Rechnung `R-2026-000099` mit Altdaten-Position (`produktReferenz`/`einzelpreisNetto`/`positionssummeNetto` = `null`) | `exportiere(rechnung, ziel)` | kein Fehler (`assertDoesNotThrow`); PDF-Datei existiert |
| TC-17 | F-23 (Robustheit) | Rechnung `R-2026-000098` mit `null`-Positionssummen | Summen berechnen | summeNetto = summeSteuer = summeBrutto = 0.00 (Scale 2) |
#### 2.1.4 CSV-Datenexport der Belege (`DokumentCsvExportTest`)
| TC | Abgedeckte PH-Anf. | Vorbedingung | Eingabe | Erwartetes Ergebnis |
|---------|------------|------------------------|----------------------|----------------------------|
| TC-18 | Q-08, IF-04 | Repository mit 2 Rechnungen (je 1 Position); eine storniert (Datum 2026-06-10, Benutzer „Anwender") | `exportiereCsv(ziel)` | CSV mit Kopfzeile `belegnummer;belegtyp;datum;status…` + je Position eine Zeile (3 Zeilen); enthält `R-2026-000001` sowie `STORNIERT`/`Anwender` |
### 2.2 Komponente B — Produktverwaltung
PH-Anf.-Nummern beziehen sich auf das Pflichtenheft Gruppe B. Die Schnittstelle
`ProduktReferenzPruefung` (Gruppe A) wird durch einen Stub ersetzt.
| TC | Abgedeckte PH-Anf. | Vorbedingung | Eingabe | Erwartetes Ergebnis |
|---------|------------|------------------------|----------------------|----------------------------|
| TC-01 | F-01, F-02 | Höchste Produktnummer `P-000041` | Produkt („Beratungsstunde", 80.00, 0.19) speichern | Produkt persistiert; Produktnummer = `P-000042` |
| TC-02 | F-02 (Format) | Zähler = 7 | `naechsteNummer()` | liefert `P-000007` (führende Nullen, `String`) |
| TC-03 | F-03 | gültiges Produkt | Einzelpreis `-1.00` | Speichern abgelehnt (Validierungsfehler „Einzelpreis") |
| TC-04 | F-03 | gültiges Produkt | Steuersatz `0.15` | Speichern abgelehnt (unzulässiger Steuersatz) |
| TC-05 | F-04, NF-USE-01 | Produkt ohne Bezeichnung | `speichere()` | Speichern abgelehnt; Validierungsfehler benennt „Bezeichnung" |
| TC-06 | F-05 | Produkt `P-000042` mit Preis 80.00 | Preis auf 95.00 ändern, speichern | gespeichertes Produkt hat einzelpreisNetto = 95.00 |
| TC-07 | F-07 | Produkt `P-000042` | Änderungsversuch der Produktnummer auf `P-999999` | wirft `IllegalArgumentException` / Änderung abgelehnt |
| TC-08 | F-08 | Produkt unverknüpft (Stub: `istProduktReferenziert``false`) | `loescheProdukt("P-000011")` mit Bestätigung | Produkt entfernt; nicht mehr in `alleSortiertNachBezeichnung()` |
| TC-09 | F-09, F-10 | Stub: `istProduktReferenziert("P-000010")``true` | `loescheProdukt("P-000010")` | Löschen abgelehnt; Produkt weiterhin vorhanden; Hinweis erzeugt |
| TC-10 | F-11 | Produkte „Zaun", „Anker", „Mast" | `alleSortiertNachBezeichnung()` | Reihenfolge: „Anker", „Mast", „Zaun" |
| TC-11 | F-12 | Produkt „Beratungsstunde" | `suche("BERATUNG")` | Trefferliste enthält „Beratungsstunde" (case-insensitive, Teilstring) |
| TC-12 | F-12 | Produkt `P-000042` | `suche("P-000042")` | Trefferliste enthält genau dieses Produkt |
| TC-13 | F-14 | Kein Produkt `P-999999` vorhanden | `findeProdukt("P-999999")` | liefert `null` |
| TC-14 | F-15 | 3 Produkte im Bestand | `exportiereCsv(ziel)` | CSV-Datei mit Kopfzeile + 3 Datenzeilen, Semikolon-getrennt, UTF-8 |
### 2.3 Komponente C — Kundenverwaltung
PH-Anf.-Nummern beziehen sich auf das Pflichtenheft Gruppe C. Die Schnittstelle
`KundenReferenzPruefung` (Gruppe A) wird durch einen Stub ersetzt.
| TC | Abgedeckte PH-Anf. | Vorbedingung | Eingabe | Erwartetes Ergebnis |
|---------|------------|------------------------|----------------------|----------------------------|
| TC-01 | F-01, F-02 | Höchste Kundennummer `K-000016` | Kunde („Muster GmbH", „Hauptstr. 1", „68163", „Mannheim") speichern | Kunde persistiert; Kundennummer = `K-000017` |
| TC-02 | F-02 (Format) | Zähler = 7 | `naechsteNummer()` | liefert `K-000007` (führende Nullen, `String`) |
| TC-03 | F-03, NF-USE-01 | Kunde ohne Ort | `speichere()` | Speichern abgelehnt; Validierungsfehler benennt „Ort" |
| TC-04 | F-03 | Kunde mit leerem Namen (`""`) | `speichere()` | Speichern abgelehnt; Validierungsfehler benennt „Name" |
| TC-05 | F-04 | Kunde mit E-Mail `"max.mustermann"` | `speichere()` | Speichern abgelehnt (ungültiges E-Mail-Format) |
| TC-06 | F-04 | Kunde mit E-Mail `"max@beispiel.de"` | `speichere()` | Kunde gespeichert (gültiges Format) |
| TC-07 | F-05 | Kunde `K-000017` mit Ort „Mannheim" | Ort auf „Heidelberg" ändern, speichern | gespeicherter Kunde hat ort = „Heidelberg" |
| TC-08 | F-07 | Kunde `K-000017` | Änderungsversuch der Kundennummer auf `K-999999` | wirft `IllegalArgumentException` / Änderung abgelehnt |
| TC-09 | F-08 | Stub: `anzahlVerknuepfterDokumente``0` | `loescheKunde("K-000011")` mit Bestätigung | Kunde entfernt; nicht mehr in `alleSortiertNachName()` |
| TC-10 | F-09, F-10, GR-04 | Stub: `anzahlVerknuepfterDokumente("K-000010")``3` | `loescheKunde("K-000010")` | Löschen abgelehnt; Kunde weiterhin vorhanden; Hinweis enthält Anzahl `3` |
| TC-11 | F-11 | Kunden „Zimmer", „Albrecht", „Maier" | `alleSortiertNachName()` | Reihenfolge: „Albrecht", „Maier", „Zimmer" |
| TC-12 | F-12 | Kunde „Muster GmbH" | `suche("MUSTER")` | Trefferliste enthält „Muster GmbH" (case-insensitive, Teilstring) |
| TC-13 | F-12, F-14 | Kunde `K-000017` vorhanden; `K-999999` nicht | `suche("K-000017")`; `findeKunde("K-999999")` | Treffer enthält `K-000017`; `findeKunde` liefert `null` |
| TC-14 | F-15 | 3 Kunden im Bestand | `exportiereCsv(ziel)` | CSV-Datei mit Kopfzeile + 3 Datenzeilen, Semikolon-getrennt, UTF-8 |
### 2.4 Komponente D — Programmoberfläche
PH-Anf.-Nummern beziehen sich auf das Pflichtenheft Gruppe D. Getestet wird die GUI-freie
Controller- und Modell-Schicht; die Service-Schnittstellen der Gruppen AC werden durch
Stubs/Mocks ersetzt.
| TC | Abgedeckte PH-Anf. | Vorbedingung | Eingabe | Erwartetes Ergebnis |
|---------|------------|------------------------|----------------------|----------------------------|
| TC-01 | F-09 | Wizard neu gestartet | `aktuellerSchritt` lesen | `KUNDE_WAEHLEN` (erster Schritt) |
| TC-02 | F-09 | Schritt 1 mit gewähltem Kunden | `weiter()` 4-mal mit gültigen Eingaben | Schrittfolge: `POSITIONEN_ERFASSEN``DATEN_BESTAETIGEN``ZUSAMMENFASSUNG``SPEICHERN` |
| TC-03 | F-10 | Schritt 1, kein Kunde gewählt (`kundenNr = null`) | `weiter()` | Wechsel verhindert; `Meldung(FEHLER, "Kunde", …)` erzeugt |
| TC-04 | F-10 | Schritt 2, leere Positionsliste | `weiter()` | Wechsel verhindert; Meldung benennt „Position" |
| TC-05 | F-10 | Schritt 2, Position mit `menge = 0` | `weiter()` | Wechsel verhindert; Meldung benennt „Menge" |
| TC-06 | F-11 | Schritt 3 erreicht; Kunde `K-000017`, 1 Position erfasst | `zurueck()` bis Schritt 1 | `kundenNr` und `positionen` unverändert erhalten |
| TC-07 | F-12 | Schritt 4; Stub `DokumentService` liefert Summen 200.00/38.00/238.00 | Zusammenfassung erzeugen | Zusammenfassung enthält Kunde, Positionen, Mengen, 200.00/38.00/238.00, Rechnungsdatum, Zahlungsziel |
| TC-08 | F-13 | Schritt 5; gültiges Modell | `speichern()` | genau **ein** Aufruf `erstelleRechnung(...)` am Mock; Erfolgsmeldung enthält gelieferte Rechnungsnummer |
| TC-09 | F-13 (Fehlerfall) | Stub `erstelleRechnung` wirft Validierungsfehler „Rechnungsdatum" | `speichern()` | keine Erfolgsmeldung; `Meldung(FEHLER, "Rechnungsdatum", …)` dargestellt (F-05/F-16) |
| TC-10 | F-14 | Dokumentliste mit Rechnungen in `OFFEN`, `VERSENDET`, `STORNIERT` | verfügbare Aktionen je Rechnung ermitteln | *Stornieren* nur bei Status `OFFEN` aktiviert |
| TC-11 | F-15 | Rechnung `R-2026-000124` | `storniere()` ohne Bestätigung; danach mit Bestätigung | ohne Bestätigung: kein Service-Aufruf; mit Bestätigung: genau ein Aufruf `storniere("R-2026-000124")` |
| TC-12 | F-08 | Beleg im Status `VERSENDET` | Änderungsaktionen ermitteln | alle inhaltlichen Änderungsaktionen deaktiviert; PDF-Export aktiviert |
| TC-13 | F-06 | Belege mit Status `OFFEN` (2×) und `STORNIERT` (1×) | Statusfilter `OFFEN` anwenden | Liste enthält genau die 2 offenen Belege |
| TC-14 | F-03 | Stub `KundenService.suche("Muster")` liefert 1 Treffer | Suchbegriff „Muster" eingeben | Controller delegiert an `KundenService.suche(...)`; Trefferliste enthält genau diesen Kunden |
| TC-15 | F-03 (D-F-03) | Stub `KundenService` mit 1 Kunden „Muster GmbH" | `kundenListe("")`, `(" ")`, `(null)`, `("Muster")`, `("unbekannt")` | leerer/fehlender Suchbegriff: gesamter Bestand (1); „Muster": 1 Treffer; „unbekannt": 0 Treffer |
### 2.5 Gemeinsame Infrastruktur (Paket `gemeinsam`)
Querschnittliche Dienste, die von allen Komponenten genutzt werden. Der `EreignisBus`
(Observer-Muster) ist in der Architektur der Komponente A (Pflichtenheft A §7) verortet;
`JsonPersistenz` ist die gemeinsame atomare JSON-Ablage hinter allen Repositories (IF-01).
#### 2.5.1 Ereignisbenachrichtigung (`EreignisBusTest`)
| TC | Abgedeckte Anf. | Vorbedingung | Eingabe | Erwartetes Ergebnis |
|---------|------------|------------------------|----------------------|----------------------------|
| INF-01 | Observer (PH-A §7) | `EreignisBus` mit 2 Beobachtern für Bereich `KUNDEN` | `melde(KUNDEN)` 2× | beide Beobachter genau 2× benachrichtigt |
| INF-02 | Observer | Beobachter für `KUNDEN` und `DOKUMENTE` | `melde(DOKUMENTE)` | nur `DOKUMENTE`-Beobachter (1×); `KUNDEN`-Beobachter 0× |
| INF-03 | Observer (Robustheit) | `EreignisBus` ohne Beobachter | `melde(PRODUKTE)` | wirkungslos, keine Exception |
#### 2.5.2 Atomare JSON-Persistenz (`JsonPersistenzTest`)
| TC | Abgedeckte Anf. | Vorbedingung | Eingabe | Erwartetes Ergebnis |
|---------|------------|------------------------|----------------------|----------------------------|
| INF-04 | IF-01 (atomar) | leeres Verzeichnis | `schreibeAtomar(datei, ["a","b"])` | Zieldatei existiert; keine `.tmp`-Restdatei; Inhalt = `["a","b"]` |
| INF-05 | IF-01 | Datei mit Bestand `["alt"]` | `schreibeAtomar(datei, ["neu1","neu2"])` | Inhalt vollständig ersetzt = `["neu1","neu2"]` |
| INF-06 | IF-01 | Zielpfad mit fehlendem Unterordner | `schreibeAtomar(unterordner/datei, ["a"])` | fehlende Elternverzeichnisse angelegt; Datei existiert |
### 2.6 Performance-/Lastnachweise (`PerformanceTest`)
Übergreifende Lastnachweise gemäß Lastenheft. Referenzgröße: 5.000 Kunden, 5.000 Produkte,
1.000 Belege (vorab geseedet; das Befüllen fließt nicht in die Messung ein). Die Spalte
*Erwartetes Ergebnis* nennt die einzuhaltende Zeitschranke.
| ID | Abgedeckte Anf. | Vorbedingung | Eingabe | Erwartetes Ergebnis (Zeitschranke) |
|---------|------------|------------------------|--------------------|------------------------------|
| Q-04 | Q-04 (Start) | Seeding 5.000 Kunden / 5.000 Produkte / 1.000 Belege (je JSON) | drei Repositories laden | Laden in ≤ 5 s |
| Q-02 | Q-02 (Suche) | Bestand wie Q-04 | Kunden-/Produktsuche + Auflistung | abgeschlossen in ≤ 1 s |
| Q-03 | Q-03 (PDF) | Rechnung mit 50 Positionen | `exportiere(rechnung, ziel)` | PDF-Erstellung in ≤ 2 s |
| Q-08 | Q-08 (Export) | Bestand wie Q-04 | Vollexport Kunden + Produkte + Belege als CSV | abgeschlossen in ≤ 30 s |
## 3. Testumfang-Übersicht
| Testklasse | Komponente | Anzahl |
|------------|-----------|--------|
| `dokumente/DokumentzyklusTest` | A Prozess/Dokumentenzyklus | 13 |
| `dokumente/JsonDokumentRepositoryTest`| A Belegpersistenz (IF-01/GoBD) | 1 |
| `dokumente/PdfBoxPdfExporterTest` | A PDF-Export (F-15) | 3 |
| `dokumente/DokumentCsvExportTest` | A CSV-Export Belege (Q-08) | 1 |
| `produkte/ProduktVerwaltungTest` | B Produktverwaltung | 14 |
| `kunden/KundenVerwaltungTest` | C Kundenverwaltung | 14 |
| `gui/OberflaechenControllerTest` | D Programmoberfläche | 15 |
| `gemeinsam/EreignisBusTest` | Gemeinsame Infrastruktur (Observer) | 3 |
| `gemeinsam/JsonPersistenzTest` | Gemeinsame Infrastruktur (Persistenz) | 3 |
| `PerformanceTest` | Querschnitt (Q-02/Q-03/Q-04/Q-08) | 4 |
| **Summe** | | **71** |
Damit sind **71 Testfälle** über alle vier Komponenten, die gemeinsame Infrastruktur und die
Performance-Nachweise spezifiziert. Sie decken die funktionalen Kernregeln, die zentralen
Geschäftsregeln (GR-01…GR-06) sowie die Qualitäts-/Performanceanforderungen (Q-02, Q-03,
Q-04, Q-08, Q-09) ab.
## 4. Abkürzungen
| Abkürzung | Bedeutung |
|-----------|-----------|
| TC | Testfall (Test Case) |
| F | Funktionale Anforderung (Pflichtenheft) |
| INF | Infrastruktur-Testfall (Paket `gemeinsam`) |
| F | Funktionale Anforderung (Pflichtenheft, komponentenlokal) |
| NF | Nicht-funktionale Anforderung (Pflichtenheft) |
| IF | Schnittstelle (Interface) |
| GR | Geschäftsregel (Lastenheft) |
| Q | Qualitätsanforderung (Lastenheft) |
| PH | Pflichtenheft |
| CSV | Comma-Separated Values (offenes Exportformat) |
| GoBD | Grundsätze zur ordnungsmäßigen Führung und Aufbewahrung von Büchern |

BIN
Modultestplan.pdf 100644

Binary file not shown.

View File

@ -50,7 +50,7 @@ und den Modultest der Komponente *Prozess / Dokumentenzyklus*.
|---------|------------|-----------------------------|---------------------|
| 1.0 | 09.06.2026 | Lucas Strubel | Initiale Erstellung |
| 1.1 | 13.06.2026 | Lucas Strubel | Einfügen der UML-Diagramme (Klassen- und Sequenzdiagramm) |
| 1.2 | 15.06.2026 | Lucas Strubel | Modultestplan in eigenständiges Dokument (Modultestplan_GruppeA.md) ausgegliedert |
| 1.2 | 15.06.2026 | Lucas Strubel | Modultestplan in eigenständiges Dokument (Modultestplan.md) ausgegliedert |
\newpage
@ -62,7 +62,7 @@ Auftragnehmers, **wie** die Komponente *Prozess / Dokumentenzyklus* der
Desktop-Fakturierungsanwendung die Anforderungen des Lastenhefts (v1.3) erfüllt. Es
konkretisiert die fachlichen Anforderungen in testbare Systemanforderungen und dient als
direkte Grundlage für Design, Implementierung sowie den Komponenten- bzw. Modultestplan
(eigenständiges Dokument *Modultestplan_GruppeA.md*).
(eigenständiges Dokument *Modultestplan.md*).
### 1.2 Ziel
Ziel dieses Pflichtenhefts ist die vollständige und testbare Spezifikation der Erzeugung,
@ -286,7 +286,7 @@ erfolgt (Nachweis durch Netzwerk-Monitoring während eines repräsentativen Nutz
## 6. Daten und Schnittstellen
Dieses Kapitel ist direkter Input für den Modultestplan (eigenständiges Dokument *Modultestplan_GruppeA.md*). Datentypen werden
Dieses Kapitel ist direkter Input für den Modultestplan (eigenständiges Dokument *Modultestplan.md*). Datentypen werden
bereits als Java-Typen angegeben.
### 6.1 Datenobjekte und Datentypen
@ -369,7 +369,7 @@ exportieren (Q-08).
**Interne Schnittstellen:** Die Schnittstellen werden hier **fachlich** beschrieben
(Zweck, ausgetauschte Daten, Richtung); konkrete Methodensignaturen
und Datentypen sind dem Komponentenentwurf bzw. dem Modultestplan (eigenständiges Dokument *Modultestplan_GruppeA.md*) vorbehalten.
und Datentypen sind dem Komponentenentwurf bzw. dem Modultestplan (eigenständiges Dokument *Modultestplan.md*) vorbehalten.
*Genutzte Schnittstellen (Komponente A ruft auf):*