werkcrappit computes an experimental Mutation-CRAP score per JVM method from the JaCoCo complexity of the original class files and the PIT mutation score. The specification is docs/pitest-mutation-crap-coding-agent-auftrag.md. This commit holds only the skeleton: Gradle 9.8.0 wrapper, Java 21 toolchain with JUnit Jupiter and AssertJ, the modules werkcrappit-pit and werkcrappit-gradle-plugin (with a no-op plugin class), README, AGENTS.md and LICENSE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
885 lines
60 KiB
Markdown
885 lines
60 KiB
Markdown
# Implementierungsauftrag: Mutation-CRAP als eigenständiges PIT-Plugin
|
||
|
||
**Adressat:** Codex oder ein anderer Coding Agent
|
||
**Arbeitsname:** `pitest-mutation-crap`
|
||
**Stand:** 1. Oktober 2026
|
||
**Ziel:** Ein funktionierendes, getestetes Plugin implementieren, nicht nur einen Entwurf erstellen.
|
||
|
||
## 1. Auftrag und Motivation
|
||
|
||
Implementiere in einem eigenständigen Git-Repository ein **Reporting-Plugin für PIT / PITest**, das für JVM-Methoden einen mutationsbasierten CRAP-Wert berechnet. Die Integration und die unterstützten Anwender-Workflows erfolgen ausschließlich über **Gradle**. Java hat höchste Priorität; Kotlin/JVM ist ein nachgeordnetes Kompatibilitätsziel.
|
||
|
||
Gemeint ist **PIT für Mutation Testing auf der JVM**, nicht das Python-Testframework pytest.
|
||
|
||
Die Motivation: Wir möchten Methoden identifizieren, bei denen hohe strukturelle Komplexität mit einer geringen Fähigkeit der Tests zusammenkommt, die von PIT erzeugten Verhaltensänderungen zu erkennen. Dafür kombinieren wir Mutationsergebnisse aus PIT mit der zyklomatischen Komplexität derselben Methode aus JaCoCo Core.
|
||
|
||
Die vorgeschlagene Mutation-CRAP-Formel ist für dieses Projekt eine **experimentelle, ausdrücklich definierte Metrik**. Behaupte weder, sie sei ein offizieller CRAP-Nachfolger, noch, ihre Überlegenheit oder ein bestimmter Grenzwert seien empirisch bewiesen. Die erste Version soll die praktische Erprobung ermöglichen. Eine spätere Evaluation darf die Definition ändern, aber nur mit neuer Metrikversion und dokumentierter Entscheidung.
|
||
|
||
Arbeite in überprüfbaren vertikalen Schritten: zuerst ein echter Gradle/PIT-Durchstich, anschließend Berechnung, Reports und optional einschaltbare Build-Prüfung. Erzeuge nicht zuerst eine umfangreiche Architektur ohne funktionierenden Integrationsnachweis.
|
||
|
||
## 2. Verbindlicher Rahmen und Abgrenzung
|
||
|
||
### 2.1 Bereits festgelegte Anforderungen
|
||
|
||
- Eigenständiges Repository und unabhängig versioniertes PIT-Plugin; kein Fork und keine Änderung am PIT-Core als Voraussetzung.
|
||
- Gradle als einziges unterstütztes Buildsystem. Kein Maven-Plugin, kein Maven-Beispielprojekt und keine Maven-Testmatrix erforderlich.
|
||
- JVM als Zielplattform, Java als verbindliches erstes Sprachziel. Kotlin/JVM nach Möglichkeit unterstützen; andere JVM-Sprachen nicht pauschal als unterstützt bewerben.
|
||
- Mutationsergebnisse direkt aus der PIT-Listener-/Plugin-Schnittstelle beziehen, nicht aus einem nachgeschalteten Import von `mutations.xml`.
|
||
- Komplexität mit **JaCoCo Core aus den originalen, unmutierten Class-Dateien** ermitteln.
|
||
- Beide Datenquellen über Klassenname, JVM-Methodenname und JVM-Methodendeskriptor verbinden.
|
||
- Kein eigener Coverage-Testlauf, kein JaCoCo-Agent und keine JaCoCo-`.exec`-Datei als Voraussetzung für diese Metrik.
|
||
- Kein zusätzlicher PIT-Lauf, den die Metrikberechnung auslöst. PITs eigene Testausführung und vorbereitende Coverage-Ermittlung bleiben davon unberührt.
|
||
- Maschinenlesbarer Report und ein in CI gut lesbarer Report; zusätzlich eine optional einschaltbare Grenzwertprüfung.
|
||
- Gradle-Multi-Project-Builds berücksichtigen, zunächst mit getrennten Auswertungen pro Teilprojekt beziehungsweise PIT-Analyse.
|
||
- Explizite Ausschlüsse ermöglichen. Statusbehandlung, fehlende Daten und Aussagegrenzen müssen nachvollziehbar sein.
|
||
|
||
Ein PIT-Plugin ist hier ein von PIT geladenes JAR. Das vorhandene Gradle-PIT-Plugin kann solche Abhängigkeiten laden; ein eigenes Gradle-Plugin ist deshalb **nicht die Voraussetzung für die Metrikimplementierung**. [S1][S9]
|
||
|
||
### 2.2 Nicht Bestandteil der ersten Version
|
||
|
||
Keine eigene Mutation Engine, keine neuen Mutatoren, keine automatische Erkennung äquivalenter Mutanten und keine eigene Implementierung zyklomatischer Komplexität. Ebenso wenig: eigenständige CLI, zentraler Server, Webdienst, SonarQube-Integration, IDE-Plugin, Git-Hosting-Anbindung oder automatische PR-Kommentare.
|
||
|
||
Ein projektübergreifender Gesamtreport, Baselines und ein Gate ausschließlich für geänderte Methoden sind mögliche spätere Erweiterungen. Implementiere sie nicht vor dem funktionierenden Java-MVP. Addiere nicht einfach Methodenwerte zu einer angeblich etablierten „Projekt-CRAP-Metrik“.
|
||
|
||
Kein kostenpflichtiges Add-on darf für den Java-MVP erforderlich sein. Insbesondere soll das optionale Kotlin-Ziel den Java-MVP weder blockieren noch stillschweigend eine zusätzliche Lizenz voraussetzen.
|
||
|
||
Die Veröffentlichung eines JARs in einem Maven-kompatiblen Artefakt-Repository ist von Maven als Buildsystem zu unterscheiden und ist zulässig. Eine Veröffentlichung auf externen Diensten oder das Anlegen eines Remote-Repositories gehört ohne gesonderten Auftrag nicht zur Ausführung dieses Arbeitsauftrags.
|
||
|
||
### 2.3 Konkrete Arbeitsentscheidungen dieser Spezifikation
|
||
|
||
Die folgenden Details sind bewusst gewählte Startentscheidungen, nicht bereits vorher getroffene Anwenderentscheidungen:
|
||
|
||
- Name des PIT-Ausgabeformats: `MUTATION_CRAP`.
|
||
- Metrikkennung: `mutation-crap`; initiale Metrikversion: `1`.
|
||
- Statuspolicy: `strict-v1`, definiert in Abschnitt 5.
|
||
- Primäre Ausgabe: JSON; lesbare Ausgabe: Markdown plus kurze Konsolenzusammenfassung.
|
||
- Standardmodus: Report erstellen, aber keinen Build allein wegen eines hohen Scores abbrechen.
|
||
- Ein aktiviertes Score-Gate verlangt einen ausdrücklich konfigurierten Grenzwert. **30 ist nur ein Testbeispiel, keine Empfehlung und kein impliziter Standardwert.**
|
||
- Neue Produktionslogik vorzugsweise in Java, Buildskripte vorzugsweise als Gradle Kotlin DSL. Java-Code mit `var` beziehungsweise `final var`, wo dies mit der gewählten Java-Version und der Lesbarkeit vereinbar ist.
|
||
- Tests mit JUnit Jupiter und AssertJ; Mockito nur dort, wo ein Testdouble sinnvoller ist als ein kleines reales Fixture.
|
||
|
||
Dokumentiere notwendige Änderungen dieser Arbeitsentscheidungen. Ändere nicht unbemerkt die Metrikformel, ihre Statuspolicy oder die verbindlichen Rahmenbedingungen.
|
||
|
||
## 3. Zuerst die technische Machbarkeit nachweisen
|
||
|
||
### 3.1 Was bereits belegt ist — und was nicht
|
||
|
||
PIT bietet `MutationResultListenerFactory` als Erweiterungspunkt für Ergebnis-Plugins. Listener werden als Service registriert; ein Ausgabeformat kann über `outputFormats` aktiviert werden. Die dokumentierten Erweiterungsschnittstellen sind allerdings nicht als über alle Versionen unveränderlich zugesagt. [S1][S2]
|
||
|
||
Der untersuchte Listener besitzt `runStart()`, `handleMutationResult(ClassMutationResults)` und `runEnd()`. **Eine Klasse kann auf mehrere `ClassMutationResults`-Instanzen verteilt sein.** Daher darf ein einzelner Callback nicht als vollständiges Klassenergebnis behandelt werden. [S3]
|
||
|
||
JaCoCo stellt die Analyse von Class-Dateien und Methodencounter bereit. Der Analyzer behandelt auch Klassen ohne vorhandene Ausführungsdaten; die statische Komplexität ist damit ohne zusätzlichen Coverage-Lauf ableitbar. Für die Berechnung ist der gesamte Complexity-Counter zu verwenden, nicht dessen abgedeckter Anteil. [S6][S7]
|
||
|
||
Noch kein ausgeführter Integrationsnachweis liegt dafür vor, dass die hier geplante Kombination mit einer konkreten Versionenauswahl in Gradle funktioniert. Diesen Nachweis musst du als ersten Implementierungsschritt liefern.
|
||
|
||
### 3.2 Versionen reproduzierbar auswählen
|
||
|
||
Prüfe die zum Implementierungszeitpunkt verfügbaren stabilen Versionen von PIT, `info.solidsoft.pitest`, JaCoCo, dem PIT-JUnit-5-Plugin, JUnit und Gradle. Wähle eine tatsächlich kompatible Kombination und pinne sie einschließlich Gradle Wrapper und Java Toolchain.
|
||
|
||
Unterscheide Build-JDK, Laufzeit-JDK des PIT-Prozesses und Bytecode-Zielversion. Behaupte keine Kompatibilität allein aufgrund einer Abhängigkeitsauflösung oder eines erfolgreichen Kompiliervorgangs.
|
||
|
||
Die Quellen am Ende dieses Auftrags verweisen teilweise auf `master` oder `trunk`. Sie dienen zur Orientierung; überprüfe die benötigten APIs am gewählten Release-Tag oder an dessen veröffentlichten Artefakten. Keine dynamischen Versionen oder Snapshot-Abhängigkeiten für den regulären Build. Dokumentiere die erste erfolgreich getestete Versionenkombination in `docs/compatibility.md`.
|
||
|
||
### 3.3 Minimaler Durchstich
|
||
|
||
Baue ein kleines Java-Anwenderprojekt mit einer verzweigenden Methode und JUnit-Jupiter-Tests. Lade das **wirklich gebaute Plugin-JAR** über den PIT-Tool-Classpath. Ein Test, der nur direkt die Listenerklasse instanziiert, reicht dafür nicht.
|
||
|
||
Der Durchstich muss nachweisen, dass:
|
||
|
||
1. PIT die Factory aus dem ausgelieferten Service-Eintrag findet und `MUTATION_CRAP` aktiviert.
|
||
2. Mutationsergebnisse mit vollständiger Methodenidentität ankommen.
|
||
3. das Plugin genau die zugehörigen originalen Class-Dateien erhält und JaCoCo sie analysiert.
|
||
4. beide Datenquellen eindeutig zusammengeführt werden und ein Report im vorgesehenen Ausgabeverzeichnis entsteht.
|
||
5. normale PIT-Ausgaben parallel möglich bleiben und keine zusätzliche Testausführung für JaCoCo stattfindet.
|
||
|
||
Verwende zunächst eine einzige unterstützte Versionenkombination. Erst danach eine kleine, begründete Kompatibilitätsmatrix ergänzen.
|
||
|
||
### 3.4 Bytecodezugriff nicht voraussetzen
|
||
|
||
**`ListenerArguments.getLocator()` ist kein Bytecodezugriff:** Es liefert im untersuchten Stand einen `SourceLocator`, der Quelltext als `Reader` sucht. Über diese API dürfen keine `.class`-Bytes erwartet werden. [S4]
|
||
|
||
Der untersuchte Stand bietet dagegen über `ListenerArguments.data()` Zugriff auf `ReportOptions`; dort existieren unter anderem Classpath- und Codepath-Informationen. Das ist ein Kandidat für einen gekapselten Adapter, noch keine Zusage für jede PIT-Version. [S4][S5]
|
||
|
||
Prüfe in dieser Reihenfolge:
|
||
|
||
1. Gibt es in der gewählten PIT-Version einen geeigneten verfügbaren Bytecode-/Classpath-Zugang für das Ergebnis-Plugin?
|
||
2. Lassen sich ansonsten die im PIT-Aufruf vorhandenen Classpath- und Codepath-Daten verwenden, ohne PITs private Felder oder Reflection-Hacks zu benötigen?
|
||
3. Falls nötig: Lass eine dünne Gradle-Integration explizit die kompilierten Produktionsausgaben und erforderlichen JAR-Pfade an das Plugin übergeben. Leite diese aus dem tatsächlichen Buildmodell ab; hardcodiere keine `build/classes/java/main`-Annahme.
|
||
|
||
Lade die Zielklassen nicht per Reflection, um ihre Bytes zu untersuchen. Analysiere keine mutierten Klassen und keine zusätzlich für Coverage instrumentierte Fassung. Erhalte Classpath-Reihenfolge, Klassenfilter und die eindeutige Herkunft der Bytes.
|
||
|
||
Ein ergänzender PIT-Erweiterungspunkt ist nur nach einem konkreten Nachweis der Notwendigkeit zu erwägen. Er darf keine versteckte Pflichtänderung am PIT-Core einführen. Ist keine tragfähige Lösung innerhalb des Rahmens möglich, liefere den reproduzierbaren Blocker, den funktionsfähigen Teil und eine kleine begründete Architekturentscheidung. Wechsle nicht stillschweigend zu einem XML-Tool und verkaufe es als das bestellte Plugin.
|
||
|
||
Halte das Ergebnis dieses Durchstichs in `docs/adr/0001-pit-integration.md` fest: Versionen, API-Zugang, Packaging, getesteter Ablauf und verbleibende Risiken.
|
||
|
||
## 4. Architektur und Datenermittlung
|
||
|
||
### 4.1 Verantwortlichkeiten
|
||
|
||
Trenne fachlich mindestens diese Verantwortlichkeiten, ohne für jede davon ein eigenes Gradle-Subprojekt anzulegen:
|
||
|
||
| Baustein | Aufgabe |
|
||
| --- | --- |
|
||
| Metrikkern | Methodenidentitäten, Statuspolicy, Berechnung und Gate-Entscheidung; unabhängig von PIT- und Gradle-Typen |
|
||
| JaCoCo-Adapter | Originalbytecode analysieren und Methodenkomplexität liefern |
|
||
| PIT-Adapter | Factory/Listener, Konfiguration, Klassenherkunft, Ergebnisaggregation und Lebenszyklus |
|
||
| Reportausgabe | Versioniertes JSON, Markdown, Zusammenfassung |
|
||
| Gradle-Anbindung | Plugin laden, Konfiguration durchreichen und optional ein Gate nach erfolgreichem PIT-Lauf ausführen |
|
||
|
||
Ein oder zwei Produktionsmodule reichen zunächst; ergänze ein dünnes Gradle-Modul nur bei tatsächlichem Nutzen. PIT-spezifische und JaCoCo-spezifische Datentypen sollen nicht durch den gesamten Metrikkern weitergereicht werden.
|
||
|
||
### 4.2 Herkunft der Komplexität
|
||
|
||
Verwende die öffentliche JaCoCo-Analyse-API mit einem leeren `ExecutionDataStore`, einem `Analyzer` und einem geeigneten Coverage-Visitor, beispielsweise `CoverageBuilder`. Lies für jede auswertbare `IMethodCoverage` die Gesamtkomplexität über `getComplexityCounter().getTotalCount()` aus. Der Methodenname und `getDesc()` dienen der Zuordnung. [S6][S7]
|
||
|
||
Definiere die Größe ausdrücklich als **JaCoCo-Zyklomatik**, nicht als Cognitive Complexity und nicht als beliebige quelltextbasierte McCabe-Implementierung. JaCoCo verwendet `B - D + 1`; Exception-Handling-Kanten erhöhen in dieser Definition die Komplexität nicht. Konstruktoren und statische Initialisierer können als JVM-Methoden vorkommen. [S8]
|
||
|
||
JaCoCos Filter für compilererzeugten Code beeinflussen die Analyse. Übernimm keine eigenen, scheinbar präziseren Quelltextwerte und implementiere keinen alternativen Kontrollflussgraphen. Weise die JaCoCo-Version im Report aus. Insbesondere bei Kotlin können sich Filter und damit Ergebnisse zwischen Versionen verändern. [S12]
|
||
|
||
Analysiere jede benötigte Klassenversion höchstens einmal pro PIT-Lauf. Vermeide globale statische Caches über mehrere Builds hinweg. Verwende für die Herkunftsprüfung einen Hash der analysierten Class-Datei oder eine gleichwertig belastbare Identität.
|
||
|
||
### 4.3 Methodenidentität
|
||
|
||
Die kanonische Identität innerhalb einer Analyse besteht aus:
|
||
|
||
- JVM-Klassenname in einer dokumentierten Normalform;
|
||
- JVM-Methodenname, einschließlich spezieller Namen wie `<init>`;
|
||
- vollständigem JVM-Descriptor, einschließlich Rückgabetyp.
|
||
|
||
Normalisiere Klassenbezeichnungen mit Punkt beziehungsweise Schrägstrich an genau einer Adaptergrenze. Innere Klassen behalten ihre JVM-Identität. Verwende weder Quelltextzeilen noch den Methodennamen allein als Schlüssel. PITs `Location` enthält diese identifizierenden Informationen. [S10]
|
||
|
||
Außerhalb einer einzelnen Analyse ergänze die Identität um den Analysekontext, etwa Gradle-Projektpfad plus PIT-Taskpfad. Gleiche Klassen- und Methodennamen aus unterschiedlichen Modulen dürfen nicht zusammenfallen.
|
||
|
||
Quelltextdatei, Zeilennummern und eine lesbare Signatur sind optionale Anzeigeinformationen. Ihr Fehlen darf einen sonst möglichen JVM-Join nicht verhindern.
|
||
|
||
### 4.4 Auswertungsscope und Methoden ohne Ergebnisse
|
||
|
||
Bewerte ausschließlich den ausdrücklich gewählten Produktionscode. Scanne nicht den vollständigen Test- und Abhängigkeitsclasspath als zu bewertende Anwendung.
|
||
|
||
Erstelle für diesen Scope soweit möglich ein Methodeninventar aus den originalen Produktionsklassen. Respektiere dabei die Klassen-/Methodenauswahl des PIT-Laufs und die eigenen dokumentierten Ausschlüsse. Ein Listener allein liefert keine verlässliche vollständige Liste sämtlicher Methoden des Projekts; die Vollständigkeit muss aus der Klassenauswahl und deren Analyse nachgewiesen werden.
|
||
|
||
Unterscheide unbedingt:
|
||
|
||
- Methode mit einem oder mehreren `NO_COVERAGE`-Mutanten;
|
||
- Methode ohne Mutationsergebnisse;
|
||
- Methode mit ausschließlich aus der Scoreberechnung ausgeschlossenen Mutanten;
|
||
- nicht eindeutig zuordenbare oder von JaCoCo nicht auswertbare Methode.
|
||
|
||
Fehlende Mutanten sind **keine** 100-Prozent-Testwirksamkeit und auch **kein** Mutation Score von null. Ist eine Methode im Inventar, hat aber keine Ergebnisse, bekommt sie einen nicht numerischen Auswertungszustand. Behaupte ohne weitere Informationen nicht, ob der Grund ein PIT-Filter, fehlende Mutationsmöglichkeiten oder eine begrenzte Analyse war.
|
||
|
||
Wenn eine vollständige Inventarisierung nicht zuverlässig möglich ist, kennzeichne den Scope als unvollständig. Ein Report darf dann nicht vorgeben, alle Methoden des Projekts zu bewerten. Das aktivierte strikte Gate muss einen unerwartet unvollständigen Scope als Analyseproblem behandeln.
|
||
|
||
Ein explizit auf bestimmte Klassen beschränkter, innerhalb dieser Auswahl vollständiger Lauf ist dagegen kein Fehler. Seine begrenzte Aussage muss im Report sichtbar sein.
|
||
|
||
### 4.5 Ergebnisaggregation und Nebenwirkungen
|
||
|
||
Sammle Ergebnisse bis zum Ende des Laufs. Mehrere Ergebnisblöcke einer Klasse müssen zusammengeführt werden; die Reihenfolge darf den Report nicht beeinflussen. [S3]
|
||
|
||
Identische erneut gelieferte Mutationsergebnisse anhand der PIT-Mutantenidentität nicht doppelt zählen. Widersprüchliche Endergebnisse derselben Identität sind ein Analyseproblem, kein Anlass für „last write wins“. Verwechsle vorläufige interne Zustände nicht mit zusätzlichen Mutanten.
|
||
|
||
Prüfe das tatsächliche Threading-Modell der gewählten API. Verwende einen pro Lauf isolierten Zustand und sichere ihn bei Bedarf gegen nebenläufige Aufrufe. Speichere möglichst Identitäten und Zähler statt unnötig vollständiger PIT-Objektgraphen.
|
||
|
||
Das Plugin ist ein Beobachter: Es darf weder Mutanten herausfiltern noch deren Status verändern, Testauswahl überschreiben oder PITs Mutator-Konfiguration austauschen. Eigene Reporting-Ausschlüsse wirken nur auf diese Metrik.
|
||
|
||
### 4.6 Packaging
|
||
|
||
Registriere die Factory korrekt unter `META-INF/services/org.pitest.mutationtest.MutationResultListenerFactory`. Stelle sicher, dass die zur Laufzeit benötigten Abhängigkeiten mitgeladen werden. PIT unterscheidet Tool-Classpath und Classpath des untersuchten Projekts. [S1]
|
||
|
||
Bündle keine zweite PIT-Distribution in das Plugin. Prüfe mögliche Versionskonflikte insbesondere mit ASM, JaCoCo und anderen PIT-Plugins. Shading/Relocation nur bei nachgewiesenem Bedarf; Service-Einträge und Lizenzhinweise müssen erhalten bleiben.
|
||
|
||
Ein Packaging-Test muss das veröffentlichungsfähige JAR samt Metadaten und Laufzeitabhängigkeiten aus einem isolierten lokalen Test-Repository konsumieren. Verlasse dich nicht auf zufällige Klassen aus der Entwicklungsumgebung.
|
||
|
||
## 5. Exakte Definition der ersten Metrikversion
|
||
|
||
### 5.1 Formel
|
||
|
||
Für eine auswertbare Methode `m` gelten:
|
||
|
||
`C(m) = zyklomatische Komplexität nach JaCoCo, mindestens 1`
|
||
|
||
`K(m) = Anzahl der Mutanten mit Status KILLED`
|
||
|
||
`S(m) = Anzahl der Mutanten mit Status SURVIVED`
|
||
|
||
`N(m) = Anzahl der Mutanten mit Status NO_COVERAGE`
|
||
|
||
`E(m) = K(m) + S(m) + N(m)`
|
||
|
||
Wenn `E(m) > 0` ist und keine in Abschnitt 5.2 definierte Uneindeutigkeit vorliegt:
|
||
|
||
`MS(m) = K(m) / E(m)`
|
||
|
||
`mutationCrap(m) = C(m)^2 × (1 − MS(m))^3 + C(m)`
|
||
|
||
`MS` ist ein Verhältnis im Intervall `[0, 1]`, kein Prozentwert im Intervall `[0, 100]`. Verwende keine ganzzahlige Division. Berechne mit hinreichender numerischer Genauigkeit; runde erst für die Anzeige, nicht vor der Grenzwertprüfung.
|
||
|
||
Definiere eine nachvollziehbare numerische Vergleichsstrategie. Ein mathematisch auf dem Grenzwert liegendes Ergebnis darf nicht aufgrund eines vermeidbaren Gleitkommaartefakts durchfallen. Da die Eingangszähler ganzzahlig sind, ist auch ein Vergleich anhand der rationalen Formel möglich. Du musst dafür kein allgemeines Numerikframework bauen.
|
||
|
||
| C | K | S | N | MS | Mutation-CRAP |
|
||
| ---: | ---: | ---: | ---: | ---: | ---: |
|
||
| 1 | 0 | 1 | 0 | 0 | 2 |
|
||
| 10 | 0 | 10 | 0 | 0 | 110 |
|
||
| 10 | 5 | 5 | 0 | 0.5 | 22.5 |
|
||
| 10 | 8 | 2 | 0 | 0.8 | 10.8 |
|
||
| 10 | 10 | 0 | 0 | 1 | 10 |
|
||
| 30 | 10 | 0 | 0 | 1 | 30 |
|
||
|
||
Diese Zahlen sind berechnete Testorakel, keine empirischen Qualitätsklassen. Bei vollständiger Mutantenerkennung entspricht der Score weiterhin der Komplexität. Eine Methode mit `C > Grenzwert` kann das entsprechende Gate daher auch mit `MS = 1` nicht bestehen.
|
||
|
||
### 5.2 Statuspolicy `strict-v1`
|
||
|
||
Verwende eine explizite Zuordnung. **Übernimm nicht pauschal `DetectionStatus.isDetected()` als Zähler:** Im untersuchten PIT-Stand ist dieses Flag auch für verschiedene Fehlerzustände und `EQUIVALENT` wahr. [S11]
|
||
|
||
| PIT-Status | Behandlung für diese Metrik |
|
||
| --- | --- |
|
||
| `KILLED` | In Zähler und Nenner |
|
||
| `SURVIVED` | Nur im Nenner |
|
||
| `NO_COVERAGE` | Nur im Nenner; nicht herausfiltern |
|
||
| `EQUIVALENT`, sofern die PIT-Version diesen Status liefert | Weder Zähler noch Nenner; separat ausweisen |
|
||
| `NON_VIABLE` | Weder Zähler noch Nenner; separat ausweisen |
|
||
| `TIMED_OUT` | Uneindeutig: betroffene Methode erhält keinen regulären Score |
|
||
| `MEMORY_ERROR`, `RUN_ERROR` | Uneindeutig: betroffene Methode erhält keinen regulären Score |
|
||
| `NOT_STARTED`, `STARTED`, falls am Ende noch vorhanden | Unvollständig: betroffene Methode erhält keinen regulären Score |
|
||
| Jeder nicht ausdrücklich unterstützte Status | Nicht stillschweigend werten; als Analyseproblem ausweisen |
|
||
|
||
Diese konservative Policy ist eine **Projektentscheidung**, keine Behauptung über PITs eigene Scoredefinition. Ein Timeout kann durch eine wirksam erkannte Endlosschleife entstehen, ist hier aber ohne zusätzliche Evidenz nicht gleichbedeutend mit einem durch eine Assertion getöteten Mutanten. [S11]
|
||
|
||
Ein uneindeutiger Endstatus macht den regulären Score der betroffenen Methode ungültig, selbst wenn es daneben genügend `KILLED`- oder `SURVIVED`-Ergebnisse gibt. Andernfalls könnte das Weglassen problematischer Ergebnisse den Score verbessern. Die Rohzähler bleiben sichtbar.
|
||
|
||
Erfinde keine automatische Äquivalenzerkennung. Nur tatsächlich so klassifizierte Ergebnisse dürfen unter `EQUIVALENT` erscheinen. Das Vorhandensein dieses Status in einer API bedeutet nicht, dass PIT jeden äquivalenten Mutanten erkennen kann.
|
||
|
||
Halte Statusmapping und Formel getrennt und teste sie separat. Eine spätere Timeout-Policy darf ergänzt werden, benötigt aber eine andere Policykennung und darf nicht unbemerkt unter `strict-v1` laufen.
|
||
|
||
### 5.3 Nicht numerische Auswertungszustände
|
||
|
||
Verwende mindestens unterscheidbare Zustände mit maschinenlesbaren Gründen:
|
||
|
||
- `SCORED`: gültige Komplexität und auswertbare Mutanten vorhanden.
|
||
- `NO_MUTATION_RESULTS`: Methode im Inventar, aber ohne Mutationsergebnisse.
|
||
- `NO_ELIGIBLE_MUTANTS`: Ergebnisse vorhanden, aber nach der Policy kein Mutant im Nenner.
|
||
- `INCONCLUSIVE`: uneindeutige, unvollständige, unbekannte oder widersprüchliche Ergebnisse.
|
||
- `COMPLEXITY_UNAVAILABLE`: Ergebnis vorhanden, aber Komplexität beziehungsweise eindeutige Zuordnung fehlt.
|
||
- `EXCLUDED`: ausdrücklich von dieser Auswertung ausgenommen.
|
||
|
||
Nicht auswertbare Werte sind im JSON `null`, nicht `0`, nicht `100 %`, nicht `NaN` und nicht Infinity. Eine gültig ermittelte Komplexität darf auch bei fehlendem Mutation Score ausgewiesen werden.
|
||
|
||
Abstrakte und native Methoden ohne analysierbaren Methodenrumpf werden nicht mit einer erfundenen Komplexität bewertet. Für compilererzeugte oder durch JaCoCo gefilterte Methoden darf ein begründeter Ausschluss verwendet werden, sofern er nachgewiesen und im Report erkennbar ist. Eine beliebige fehlgeschlagene Zuordnung darf nicht als „generated“ wegdefiniert werden.
|
||
|
||
### 5.4 Aussagegrenzen
|
||
|
||
Zeige neben dem Score immer Komplexität, Mutation Score und Mutantenzahl. Ein Verhältnis aus einem einzelnen Mutanten ist keine gleich starke Evidenz wie dasselbe Verhältnis aus vielen Mutanten; die Metrik modelliert diese Unsicherheit nicht statistisch.
|
||
|
||
Vergleiche Werte nur unter Berücksichtigung von Mutatoren, Filtern, Testauswahl, Bytecode und Toolversionen. Eine Änderung dieser Bedingungen kann den Score verändern, ohne dass Produktions- oder Testcode verbessert wurde. Ein guter Score ist weder ein Korrektheitsbeweis noch ein Ersatz für Review.
|
||
|
||
Der verwendete Score schließt `NO_COVERAGE` ein. Er ist daher nicht einfach mit einem Wert gleichzusetzen, der nur bereits abgedeckte Mutanten betrachtet; PIT beschreibt die entsprechenden Ergebnisunterschiede in seinen Grundlagen. [S13]
|
||
|
||
## 6. Reports, Konfiguration und Gradle-Gate
|
||
|
||
### 6.1 JSON als belastbarer Vertrag
|
||
|
||
Liefere `mutation-crap.json` mit dokumentiertem JSON-Schema. Mindestens enthalten sein müssen:
|
||
|
||
| Ebene | Inhalte |
|
||
| --- | --- |
|
||
| Definition | `schemaVersion`, `metricId`, `metricVersion`, `scorePolicyId`, Kennung und Version des Komplexitätsproviders |
|
||
| Herkunft | Plugin- und PIT-Version, Analyse-/Projektkontext, relevante Eingabeidentitäten |
|
||
| Scope | ausgewählte Produktionsklassen beziehungsweise Scope-Beschreibung, Inventarvollständigkeit, Ausschlüsse |
|
||
| Konfiguration | wirksame metrikeigene Optionen; verfügbare PIT-Mutator-/Filter-/Testauswahl oder ausdrücklicher Hinweis auf fehlende Provenienz |
|
||
| Laufstatus | regulär abgeschlossener Report oder unvollständige Analyse; Diagnosegründe |
|
||
| Methode | kanonische ID, gegebenenfalls Anzeigeinformationen, Komplexität, Rohzähler je Status, Nenner, Mutation Score, Mutation-CRAP, Auswertungszustand und Gründe |
|
||
| Zusammenfassung | Anzahl bewerteter, unbewerteter, uneindeutiger und ausgeschlossener Methoden; größte Scores und gegebenenfalls Gate-Verletzungen |
|
||
|
||
Ein Konfigurationsfingerprint darf nur als vollständig bezeichnet werden, wenn die dafür relevanten Einstellungen tatsächlich bekannt sind. Dump nicht unkontrolliert sämtliche JVM-Properties oder Umgebungsvariablen; darunter könnten Zugangsdaten sein.
|
||
|
||
Sortiere Ausgaben deterministisch. Für dieselben Eingabedaten und dieselbe Konfiguration müssen die fachlichen Reportdaten identisch sein. Zeitstempel und Lauf-IDs sind, sofern vorhanden, ausdrücklich davon getrennte Metadaten.
|
||
|
||
Schreibe Reports so, dass ein abgebrochener Lauf nicht versehentlich einen alten erfolgreichen Report als seinen eigenen hinterlässt. Verwende beispielsweise ein laufbezogenes Zwischenartefakt und einen erst bei erfolgreichem Abschluss veröffentlichten finalen Report. Ein vorhandener Dateiname allein ist kein Abschlussnachweis.
|
||
|
||
### 6.2 Lesbare CI-Ausgabe
|
||
|
||
Liefere `mutation-crap.md` mit einer kurzen Zusammenfassung und einer nach absteigendem Score sortierten Methodenübersicht. Zeige unbewertbare Methoden und Diagnosegründe in einem eigenen Abschnitt. Include- und Exclude-Regeln müssen nachvollziehbar bleiben.
|
||
|
||
Die Konsole zeigt einen begrenzten Ausschnitt und den Reportpfad, nicht tausende Zeilen. Markdown, JSON und Konsole müssen dieselbe Berechnung verwenden. Normale PIT-HTML-/XML-Reports dürfen nicht überschrieben werden.
|
||
|
||
Eine HTML-Ausgabe oder JUnit-XML für CI-Systeme ist später möglich, aber keine Voraussetzung für den ersten Abschluss.
|
||
|
||
### 6.3 Konfiguration
|
||
|
||
Dokumentiere eine kleine, eindeutig benannte Konfiguration mit mindestens:
|
||
|
||
- Aktivierung des Ausgabeformats und Reportziel über den unterstützten PIT-/Gradle-Weg;
|
||
- optionalem Score-Gate und dessen maximalem Methodenwert;
|
||
- Reporting-Ausschlüssen für Klassen und Methoden, mit definierter Mustersemantik;
|
||
- Analysekontext für Teilprojekt beziehungsweise PIT-Task;
|
||
- bei Bedarf expliziten Originalbytecodepfaden;
|
||
- ausdrücklicher Freigabe leerer Auswertungen für absichtlich leere Module.
|
||
|
||
Halte Gate-Optionen in der Gradle-Anbindung, wenn sie dort gebraucht werden; die gesamte Konfiguration muss nicht künstlich durch PIT geschleust werden. Werte ungültige Zahlen, widersprüchliche Optionen und unbekannte metrikeigene Konfigurationsschlüssel nicht stillschweigend aus.
|
||
|
||
Schließe triviale Methoden nicht automatisch aufgrund von Namen wie `get*` aus. Nutzer dürfen solche Ausschlüsse konfigurieren; standardmäßig sollen echte auswertbare Methoden sichtbar bleiben. Synthetisch bedeutet insbesondere bei Lambdas nicht automatisch fachlich unwichtig.
|
||
|
||
### 6.4 Gate nach abgeschlossenem PIT-Lauf
|
||
|
||
Bevorzuge einen dünnen Gradle-Verification-Task, etwa `mutationCrapCheck`, der von der vorhandenen PIT-Task abhängt und den **eigenen** fertigen JSON-Report auswertet. Das ist kein Wechsel zur Auswertung des PIT-XMLs.
|
||
|
||
Die Metrikberechnung bleibt im gemeinsamen Kern beziehungsweise PIT-Plugin. Der Gradle-Task enthält keine zweite Formelimplementierung. Er wertet den Reportvertrag mit einer gemeinsamen Gate-Logik aus.
|
||
|
||
Begründung dieser Architekturentscheidung: Ein Abbruch direkt in `runEnd()` eines Listeners könnte die Finalisierung anderer Reports beeinträchtigen. Belege einen solchen direkten Fehlerpfad durch Integrationstests, falls du statt des nachgeschalteten Tasks dennoch diesen Weg wählst. Der sichere Ablauf ist: PIT beendet sich regulär, Reports sind fertig, danach entscheidet das eigene Gate.
|
||
|
||
Die Gate-Regeln der ersten Version:
|
||
|
||
1. Ohne aktiviertes Gate kein Build-Abbruch allein wegen hoher Scores.
|
||
2. Bei aktivem Gate verletzt eine bewertete, nicht ausgeschlossene Methode die Grenze genau dann, wenn `mutationCrap > maxMutationCrap`. Gleichheit besteht.
|
||
3. `INCONCLUSIVE`, unerwartet fehlende Komplexität, unerwartet unvollständiger Scope oder ein unbrauchbarer Report lassen das strikte Gate als **Analysefehler** scheitern. Das ist keine behauptete schlechte Codequalität.
|
||
4. `NO_MUTATION_RESULTS` und `NO_ELIGIBLE_MUTANTS` sind sichtbar unbewertet. Sie verletzen allein keinen numerischen Grenzwert. Das Gate darf sie nicht als erfolgreich getestete Methoden darstellen.
|
||
5. Hat eine aktiv geprüfte Analyse insgesamt keine einzige bewertbare Methode, scheitert sie als leere Auswertung, außer dies ist ausdrücklich erlaubt.
|
||
6. Fehlgeschlagene PIT-Ausführung, fehlender/abgebrochener Report oder nicht unterstützte Schemaversion dürfen nicht zu einem grünen Gate durch Lesen einer alten Datei führen.
|
||
|
||
In CI müssen die bereits erstellten Reports auch bei einer Grenzwertverletzung als Artefakte verfügbar bleiben. Hänge die teure PIT-Analyse nicht ungefragt an jeden normalen `check`-Aufruf; dokumentiere die ausdrückliche Aktivierung des Mutation-Gates im CI-Workflow.
|
||
|
||
### 6.5 Gradle-Anwenderintegration
|
||
|
||
Nutze zunächst das bestehende `info.solidsoft.pitest`. Dessen Dokumentation beschreibt das Laden generischer PIT-Plugins sowie zusätzliche Source-Sets und Multi-Project-Konfigurationen. Diese Konfigurationen müssen nicht durch eine eigene PIT-Orchestrierung ersetzt werden. [S9]
|
||
|
||
Liefere mindestens ein lauffähiges Java-Beispiel mit Kotlin DSL und eine überprüfte Groovy-DSL-Anleitung. Falls ein eigenes dünnes Gradle-Plugin erforderlich oder sinnvoll ist, beschränke es auf die oben genannten Integrationsaufgaben.
|
||
|
||
Vorhandene Unit- und Integrationstest-Source-Sets müssen über die tatsächliche PIT-Konfiguration verwendbar bleiben. Führe sie nicht selbst über einen zusätzlichen JaCoCo- oder Gradle-Testlauf aus. Einbezogene Tests werden von PIT im Rahmen seiner normalen Arbeitsweise ausgeführt.
|
||
|
||
In Multi-Project-Builds zunächst getrennte Reports und Gates pro Analyse liefern. Reportpfade dürfen bei parallelen Teilprojekten nicht kollidieren. Ein Root-Task darf diese Teilprüfungen koordinieren, ohne Methodenwerte oder Mutation Scores zu einem neuen Gesamtwert zu vermischen.
|
||
|
||
Deklariere für eigene Gradle-Tasks Eingaben, Ausgaben und Konfigurationsabhängigkeiten korrekt. Eine Änderung des Gate-Grenzwerts muss neu geprüft werden, benötigt aber keinen erneuten Mutationstest, wenn ein für dieselben Analyseinputs gültiger PIT-Report vorliegt. Verifiziere dieses Verhalten; verlasse dich nicht auf bloße Dateiexistenz.
|
||
|
||
## 7. Kotlin/JVM: begrenztes, nachgeordnetes Ziel
|
||
|
||
Nach dem Java-Durchstich ergänze ein kleines Kotlin/JVM-Fixture mit einer gewöhnlichen Methode, Verzweigungen und überladenen Funktionen. Prüfe die Zuordnung anhand tatsächlicher JVM-Namen und Descriptoren.
|
||
|
||
Betrachte Default-Argumente, Top-Level-Funktionen, Properties, Lambdas, Bridge-/synthetische Methoden, Inline-Funktionen und Suspend-Funktionen anschließend als gesonderte Kompatibilitätsfälle. Eine Quelltextfunktion muss nicht genau einer JVM-Methode entsprechen. Fasse mehrere JVM-Methoden nicht allein aufgrund gleicher Quelltextzeilen zusammen.
|
||
|
||
JaCoCo besitzt Kotlin-spezifische Filter; PIT verweist zusätzlich auf erweiterte Kotlin-Unterstützung durch Arcmutate. Daraus folgt weder eine Garantie für alle Kotlin-Konstrukte im gewählten Setup noch, dass gewöhnlicher Kotlin-Bytecode grundsätzlich nicht funktionieren kann. Prüfe das konkrete freie Setup. [S12][S14]
|
||
|
||
Kennzeichne das Ergebnis präzise, beispielsweise „Kotlin/JVM-Basismethoden mit den dokumentierten Compiler-/PIT-Versionen getestet“. Kein pauschales „Kotlin vollständig unterstützt“ aufgrund eines einzelnen grünen Tests. Nicht abbildbare Fälle erhalten eine dokumentierte Einschränkung oder einen sichtbaren nicht numerischen Zustand, keinen erfundenen Score.
|
||
|
||
Ein belegter Kotlin-Blocker darf den Java-MVP nicht blockieren. Der Abschlussbericht muss dann den tatsächlich getesteten Stand nennen.
|
||
|
||
## 8. Arbeitsweise, Tests und Lieferumfang
|
||
|
||
### 8.1 Gherkin sinnvoll einsetzen
|
||
|
||
Die folgenden Features beschreiben beobachtbare Fähigkeiten aus Sicht von Entwicklern und CI, nicht betriebswirtschaftliche Vorgänge. Das passt zu Gherkins Feature-/Scenario-Modell. Interne Klassenstrukturen oder private Methoden gehören dagegen nicht in diese Akzeptanzszenarien. [S15]
|
||
|
||
Übernimm die Featureblöcke aus Abschnitt 9 in einzelne `.feature`-Dateien unter `docs/features/`. Die Tags `@MC-...` sind stabile Anforderungs-IDs. Implementiere die zugehörigen automatisierten Nachweise mit JUnit Jupiter; ein Cucumber-Laufzeitframework ist **nicht** vorgeschrieben.
|
||
|
||
Führe `docs/acceptance-test-map.md`, das jede ID auf konkrete Testklasse/Testmethode und ihren Status abbildet. Eine syntaktisch gültige Featuredatei ist noch kein Testnachweis. Wo kein Gherkin-Runner eingesetzt wird, sage ausdrücklich, dass JUnit-Tests die Szenarien prüfen. Prüfe die Feature-Syntax mit einem geeigneten Parser oder einem gleichwertigen reproduzierbaren Test.
|
||
|
||
Die mit `@optional-kotlin` markierten Szenarien gehören nicht zum blockierenden Java-MVP. Alle anderen Szenarien sind verbindliche Akzeptanzanforderungen; Tabellenzeilen eines Szenariogrundrisses sind getrennte Testfälle.
|
||
|
||
### 8.2 Testebenen
|
||
|
||
**Metrikkern:** Formelwerte, Grenzgleichheit, alle Statusfälle, unzulässige Eingangswerte, leere Nenner und Eigenschaften wie `C <= mutationCrap <= C² + C` für gültige Werte. Für konstantes `C` darf der Score bei steigendem `MS` nicht steigen.
|
||
|
||
**Bytecode-/Adaptertests:** Kompilierte Java-Fixtures mit Verzweigungen, Schleifen, Switch, Überladungen, Konstruktoren, Lambdas sowie abstrakten/native Methoden. Prüfe auch Klassen ohne Debuginformationen. Teste die notwendige Normalisierung und bewusst fehlende oder falsche Class-Dateien. Bekannte kleine Referenzwerte und JaCoCo-Counter dienen als Orakel; keine zweite eigene Complexity-Implementierung aufbauen.
|
||
|
||
**Listener-/Reporttests:** Gestückelte und umgeordnete Ergebnisse, Duplikate, widersprüchliche Status, stabile Ausgabe, Escaping, Schema, Abbruch-/Fehlerfälle und sichere Finalisierung.
|
||
|
||
**Gradle-Funktionstests:** Nutze nach Möglichkeit Gradle TestKit und reale kleine Anwenderprojekte. TestKit ist für Tests von Buildlogik vorgesehen. [S16] Prüfe insbesondere das gepackte Plugin, JUnit-Jupiter-Integration, beide Gate-Ausgänge, zusätzliche Test-Source-Sets und zwei Teilprojekte.
|
||
|
||
**Optionaler Eigen-Mutationstest:** PIT für den Metrikkern ist sinnvoll, sobald der normale Build steht. Vermeide rekursive Builds, bei denen der Eigen-Mutationstest wieder die vollständigen PIT-Anwender-Funktionstests startet. Kein pauschales 100-Prozent-Mutationsziel ohne Behandlung äquivalenter oder ungeeigneter Mutanten.
|
||
|
||
### 8.3 Umsetzungsschritte
|
||
|
||
1. Repository und Gradle Wrapper aufsetzen, kompatible Versionen pinnen, minimalen realen Durchstich umsetzen und ADR schreiben.
|
||
2. Metrikkern mit Referenzwerten und `strict-v1` testgetrieben implementieren.
|
||
3. Originalbytecode, Methodeninventar und JaCoCo-Komplexität zuverlässig anbinden.
|
||
4. PIT-Ergebnisse vollständig aggregieren und Identitäts-/Fehlerfälle testen.
|
||
5. JSON-Schema, JSON-/Markdown-Report und Konsolenzusammenfassung liefern.
|
||
6. Optional einschaltbares Gradle-Gate und Multi-Project-Fixture fertigstellen.
|
||
7. Kotlin-Basissupport prüfen und Grenzen dokumentieren.
|
||
8. Packaging aus isoliertem Test-Repository prüfen, Dokumentation vervollständigen und tatsächliche Testresultate zusammenfassen.
|
||
|
||
Setze offene, nicht blockierende Details begründet selbst fest, statt die Umsetzung mit einer langen Liste von Rückfragen zu stoppen. Halte Architekturentscheidungen fest und behalte die Fachsemantik dieser Spezifikation bei.
|
||
|
||
### 8.4 Erwartete Repository-Artefakte
|
||
|
||
Liefere mindestens Produktionscode, Tests, Wrapper/Builddateien, korrekt gepacktes PIT-Plugin, Beispielprojekt und eine CI-taugliche lokale Buildanleitung. Hinzu kommen:
|
||
|
||
- `README.md`: Zweck, experimenteller Status, Installation, Gradle-Konfiguration, Reports, Gate und ein vollständiger Quickstart.
|
||
- `docs/metric.md`: Formel, `strict-v1`, N/A-Zustände, Grenzwerte und Aussagegrenzen.
|
||
- `docs/compatibility.md` und das Integrations-ADR.
|
||
- `docs/features/*.feature` und `docs/acceptance-test-map.md`.
|
||
- Versioniertes JSON-Schema sowie kleine erwartete Beispielreports.
|
||
- Dokumentierter Umgang mit Runtime-Abhängigkeiten und deren Lizenzhinweisen.
|
||
|
||
Wähle ohne bekannte Eigentümerangaben keine fremde reale Group-ID oder reservierte Plugin-ID. Verwende nachvollziehbare Platzhalter beziehungsweise einen lokalen Entwicklungsnamensraum. Lege eine Projektlizenz nicht im Namen des Eigentümers fest, falls sie nicht vorgegeben ist; Abhängigkeitshinweise sind dennoch zu dokumentieren.
|
||
|
||
### 8.5 Definition of Done
|
||
|
||
Der Java-MVP ist fertig, wenn ein sauberes Checkout mit dokumentierten Voraussetzungen reproduzierbar baut, das gepackte Plugin in einem realen Gradle/PIT-Lauf funktioniert und alle verbindlichen Szenarien automatisiert nachgewiesen sind. Reports müssen echte pro-Methode-Werte aus PIT und JaCoCo enthalten, nicht nur aus simulierten Testdaten.
|
||
|
||
Berichte am Ende, was implementiert und mit welchen Versionen getestet wurde, welche Befehle tatsächlich ausgeführt wurden, welche Akzeptanztests bestanden haben und welche Einschränkungen bleiben. Behaupte weder ausgeführte Tests ohne Ausführung noch Kompatibilität ohne Nachweis. Eine fehlende lokale Voraussetzung oder ein echter API-Blocker ist konkret mit Reproduktionsschritten anzugeben.
|
||
|
||
## 9. Gherkin-Features und Akzeptanzszenarien
|
||
|
||
Die folgenden Blöcke sind in jeweils eine eigene Featuredatei zu übernehmen. Englische Status- und Feldnamen sind technische Identifikatoren; die Szenariosprache ist Deutsch.
|
||
|
||
### 9.1 `01-metric.feature`
|
||
|
||
```gherkin
|
||
# language: de
|
||
Funktionalität: Mutation-CRAP pro JVM-Methode berechnen
|
||
Als Entwickler möchte ich Komplexität und Mutationsergebnisse gemeinsam sehen,
|
||
damit ich Methoden für eine genauere Prüfung priorisieren kann.
|
||
|
||
@MC-001
|
||
Szenariogrundriss: Der Score entspricht der definierten Formel
|
||
Angenommen eine Methode hat die JaCoCo-Komplexität <komplexitaet>
|
||
Und es liegen <killed> KILLED-, <survived> SURVIVED- und <uncovered> NO_COVERAGE-Ergebnisse vor
|
||
Und es liegen keine weiteren Mutationsergebnisse vor
|
||
Wenn die Methode mit der Policy "strict-v1" ausgewertet wird
|
||
Dann ist ihr Zustand "SCORED"
|
||
Und ihr Mutation Score ist <mutationScore>
|
||
Und ihr Mutation-CRAP ist <crap>
|
||
|
||
Beispiele:
|
||
| komplexitaet | killed | survived | uncovered | mutationScore | crap |
|
||
| 1 | 0 | 1 | 0 | 0 | 2 |
|
||
| 10 | 0 | 10 | 0 | 0 | 110 |
|
||
| 10 | 5 | 5 | 0 | 0.5 | 22.5 |
|
||
| 10 | 8 | 2 | 0 | 0.8 | 10.8 |
|
||
| 10 | 10 | 0 | 0 | 1 | 10 |
|
||
| 30 | 10 | 0 | 0 | 1 | 30 |
|
||
|
||
@MC-002
|
||
Szenario: Ausschließlich nicht wertbare Mutanten ergeben keinen Score
|
||
Angenommen eine Methode hat die JaCoCo-Komplexität 4
|
||
Und ihre einzigen Ergebnisse sind 2 EQUIVALENT und 1 NON_VIABLE
|
||
Wenn die Methode mit der Policy "strict-v1" ausgewertet wird
|
||
Dann ist ihr Zustand "NO_ELIGIBLE_MUTANTS"
|
||
Und ihr Mutation Score und ihr Mutation-CRAP sind null
|
||
Und ihre Komplexität und ihre Rohzähler bleiben im Report sichtbar
|
||
|
||
@MC-003
|
||
Szenario: Eine Methode ohne Ergebnisse wird nicht als gut getestet dargestellt
|
||
Angenommen eine Methode gehört zum ausgewerteten Methodeninventar
|
||
Und sie hat die JaCoCo-Komplexität 12
|
||
Und es liegt kein Mutationsergebnis für diese Methode vor
|
||
Wenn der Report erstellt wird
|
||
Dann ist ihr Zustand "NO_MUTATION_RESULTS"
|
||
Und ihr Mutation Score und ihr Mutation-CRAP sind null
|
||
Und der Report behauptet weder null noch vollständige Testwirksamkeit
|
||
|
||
@MC-004
|
||
Szenariogrundriss: Ungültige Recheneingaben werden nicht kaschiert
|
||
Angenommen eine Recheneingabe enthält <fehler>
|
||
Wenn eine numerische Metrik daraus berechnet werden soll
|
||
Dann wird die ungültige Eingabe mit einem konkreten Grund zurückgewiesen
|
||
Und es wird kein gültiger Methodenwert erzeugt
|
||
|
||
Beispiele:
|
||
| fehler |
|
||
| eine negative Anzahl getöteter Mutanten |
|
||
| einen negativen Komplexitätswert |
|
||
| Komplexität 0 für eine numerisch bewertete Methode |
|
||
```
|
||
|
||
### 9.2 `02-status-policy.feature`
|
||
|
||
```gherkin
|
||
# language: de
|
||
Funktionalität: Mutationsergebnisse nachvollziehbar gewichten
|
||
Als Nutzer möchte ich erkennen, welche Ergebnisse in den Score eingehen,
|
||
damit Ausführungsprobleme nicht als Teststärke erscheinen.
|
||
|
||
@MC-005
|
||
Szenario: Nicht abgedeckte Mutanten bleiben im Nenner
|
||
Angenommen eine Methode hat die JaCoCo-Komplexität 10
|
||
Und sie hat 4 KILLED-, 1 SURVIVED- und 5 NO_COVERAGE-Ergebnisse
|
||
Wenn sie mit der Policy "strict-v1" ausgewertet wird
|
||
Dann beträgt der Nenner 10
|
||
Und ihr Mutation Score beträgt 0.4
|
||
Und ihr Mutation-CRAP beträgt 31.6
|
||
|
||
@MC-006
|
||
Szenariogrundriss: Explizit ausgeschlossene Status erhöhen nicht die Teststärke
|
||
Angenommen eine Methode hat 1 KILLED- und 1 SURVIVED-Ergebnis
|
||
Und zusätzlich 8 Ergebnisse mit Status <status>
|
||
Wenn sie mit der Policy "strict-v1" ausgewertet wird
|
||
Dann beträgt ihr Mutation Score 0.5
|
||
Und ihr Nenner beträgt 2
|
||
Und die 8 ausgeschlossenen Ergebnisse sind separat ausgewiesen
|
||
|
||
Beispiele:
|
||
| status |
|
||
| EQUIVALENT |
|
||
| NON_VIABLE |
|
||
|
||
@MC-007
|
||
Szenariogrundriss: Uneindeutige Endergebnisse verhindern einen regulären Score
|
||
Angenommen eine Methode hat 9 KILLED-Ergebnisse
|
||
Und am Ende der Analyse ein Ergebnis mit Status <status>
|
||
Wenn sie mit der Policy "strict-v1" ausgewertet wird
|
||
Dann ist ihr Zustand "INCONCLUSIVE"
|
||
Und ihr Mutation Score und ihr Mutation-CRAP sind null
|
||
Und der auslösende Status und alle Rohzähler sind sichtbar
|
||
|
||
Beispiele:
|
||
| status |
|
||
| TIMED_OUT |
|
||
| MEMORY_ERROR |
|
||
| RUN_ERROR |
|
||
| NOT_STARTED |
|
||
| STARTED |
|
||
| UNBEKANNTER_NEUER_STATUS |
|
||
```
|
||
|
||
### 9.3 `03-complexity-and-identity.feature`
|
||
|
||
```gherkin
|
||
# language: de
|
||
Funktionalität: Komplexität und Mutanten derselben Methode verbinden
|
||
Als Entwickler möchte ich verlässliche Methodenwerte,
|
||
auch bei Überladungen oder fehlenden Quelltextinformationen.
|
||
|
||
@MC-008
|
||
Szenario: Komplexität ohne zusätzlichen Coverage-Lauf ermitteln
|
||
Angenommen ein Java-Fixture enthält eine Methode mit einer einfachen if-Verzweigung
|
||
Und die originale Class-Datei liegt vor
|
||
Und es gibt weder eine JaCoCo-exec-Datei noch einen für diese Auswertung aktiven JaCoCo-Agenten
|
||
Wenn das Plugin die Klasse statisch analysiert
|
||
Dann wird für diese Methode die JaCoCo-Gesamtkomplexität 2 ermittelt
|
||
Und dafür wird kein Test gestartet
|
||
Und es wird nicht versehentlich die abgedeckte Komplexität 0 verwendet
|
||
|
||
@MC-009
|
||
Szenario: Fehlende Debuginformationen verhindern den Join nicht
|
||
Angenommen dasselbe kleine Java-Fixture wird mit und ohne Debuginformationen kompiliert
|
||
Und für beide Varianten liegen passende Mutationsergebnisse vor
|
||
Wenn beide Varianten jeweils ausgewertet werden
|
||
Dann werden die Mutanten jeweils der korrekten JVM-Methode zugeordnet
|
||
Und die Methode hat in beiden Varianten dieselbe Gesamtkomplexität
|
||
Und fehlende Quelltextzeilen werden als nicht verfügbar dargestellt
|
||
|
||
@MC-010
|
||
Szenario: Überladene Methoden bleiben getrennt
|
||
Angenommen eine Klasse besitzt die Methoden "calculate(I)I" und "calculate(Ljava/lang/String;)I"
|
||
Und für beide Methoden liegen verschiedene Komplexitäten und Mutationsergebnisse vor
|
||
Wenn der Report erstellt wird
|
||
Dann enthält er zwei getrennte Methodenidentitäten
|
||
Und jede Methode verwendet nur ihre eigene Komplexität und ihre eigenen Mutanten
|
||
|
||
@MC-011
|
||
Szenario: Fehlender Originalbytecode wird nicht durch einen Fantasiewert ersetzt
|
||
Angenommen ein Mutationsergebnis verweist auf eine Methode
|
||
Und deren Originalklasse kann nicht zuverlässig gelesen werden
|
||
Wenn die Analyse abgeschlossen wird
|
||
Dann wird der betroffene Eintrag als "COMPLEXITY_UNAVAILABLE" ausgewiesen
|
||
Und kein Komplexitätswert wird aus Namen oder Mutantenzahl geschätzt
|
||
Und ein aktiviertes striktes Gate scheitert mit einem Analysefehler
|
||
|
||
@MC-012
|
||
Szenario: Eine Klasse ohne Ergebnis-Callback bleibt im Inventar sichtbar
|
||
Angenommen eine Produktionsklasse gehört zum ausdrücklich ausgewählten Analysescope
|
||
Und ihre ausführbaren Methoden können statisch analysiert werden
|
||
Und PIT liefert für diese Klasse keine Mutationsergebnisse
|
||
Wenn das Plugin den ausgewählten Scope vollständig inventarisiert
|
||
Dann erscheinen ihre Methoden mit Zustand "NO_MUTATION_RESULTS"
|
||
Und sie werden nicht als erfolgreich mutationsgetestet gezählt
|
||
|
||
@MC-013
|
||
Szenario: Reporting-Ausschlüsse verändern PIT nicht
|
||
Angenommen eine Methode ist durch eine ausdrückliche Reporting-Regel ausgeschlossen
|
||
Und PIT hat für diese Methode Mutationsergebnisse erzeugt
|
||
Wenn das Plugin den Report erstellt
|
||
Dann sind Ausschluss und angewendete Regel nachvollziehbar
|
||
Und diese Methode nimmt nicht am Score-Gate teil
|
||
Und die ursprünglichen PIT-Ergebnisse werden weder verändert noch entfernt
|
||
```
|
||
|
||
### 9.4 `04-pit-lifecycle.feature`
|
||
|
||
```gherkin
|
||
# language: de
|
||
Funktionalität: Ergebnisse eines PIT-Laufs vollständig und ohne Nebenwirkungen auswerten
|
||
Als CI-Nutzer möchte ich einen einzigen normalen PIT-Lauf verwenden,
|
||
ohne dass das zusätzliche Reporting die Mutationstests verändert.
|
||
|
||
@MC-014
|
||
Szenario: Mehrere Ergebnisblöcke derselben Klasse werden zusammengeführt
|
||
Angenommen eine Methode hat die JaCoCo-Komplexität 10
|
||
Und ein Ergebnisblock enthält 4 ihrer KILLED-Ergebnisse
|
||
Und ein späterer Block enthält weitere 4 KILLED- und 2 SURVIVED-Ergebnisse
|
||
Wenn der PIT-Lauf abgeschlossen ist
|
||
Dann beträgt ihr Nenner 10
|
||
Und ihr Mutation Score beträgt 0.8
|
||
Und ihr Mutation-CRAP beträgt 10.8
|
||
Und die Methodenauswertung wird nicht durch den letzten Block überschrieben
|
||
|
||
@MC-015
|
||
Szenario: Die Reihenfolge der Ergebnisblöcke beeinflusst das Ergebnis nicht
|
||
Angenommen zwei Auswertungen erhalten dieselben eindeutigen Endergebnisse
|
||
Und die Ergebnisblöcke kommen in unterschiedlicher Reihenfolge an
|
||
Wenn beide Auswertungen abgeschlossen werden
|
||
Dann sind ihre fachlichen JSON-Inhalte identisch
|
||
Und die Methoden erscheinen in derselben stabilen Sortierung
|
||
|
||
@MC-016
|
||
Szenario: Wiederholte identische Ergebnisse werden nicht doppelt gezählt
|
||
Angenommen dieselbe PIT-Mutantenidentität wird zweimal mit Endstatus KILLED geliefert
|
||
Wenn die Ergebnisse aggregiert werden
|
||
Dann erhöht diese Identität den KILLED-Zähler nur einmal
|
||
|
||
@MC-017
|
||
Szenario: Widersprüchliche Endergebnisse sind ein Analyseproblem
|
||
Angenommen dieselbe PIT-Mutantenidentität wird mit KILLED und mit SURVIVED geliefert
|
||
Wenn die Auswertung abgeschlossen wird
|
||
Dann wird der Widerspruch als "INCONCLUSIVE" dokumentiert
|
||
Und nicht einfach das zuletzt eingegangene Ergebnis verwendet
|
||
|
||
@MC-018
|
||
Szenario: Das ausgelieferte Plugin ergänzt einen normalen PIT-Lauf
|
||
Angenommen das Plugin-JAR und seine Abhängigkeiten sind über den PIT-Tool-Classpath geladen
|
||
Und MUTATION_CRAP sowie die normalen PIT-Ausgaben HTML und XML sind aktiviert
|
||
Wenn das Java-Beispielprojekt seine PIT-Analyse ausführt
|
||
Dann entstehen der eigene JSON- und Markdown-Report sowie die normalen PIT-Reports
|
||
Und das Plugin hat keine zusätzliche PIT-Analyse gestartet
|
||
Und das Plugin hat keinen zusätzlichen Coverage-Testlauf gestartet
|
||
Und es hat die Mutantenauswahl nicht verändert
|
||
```
|
||
|
||
### 9.5 `05-reports-and-gate.feature`
|
||
|
||
```gherkin
|
||
# language: de
|
||
Funktionalität: Nachvollziehbare Reports und ein bewusst aktiviertes Build-Gate liefern
|
||
Als CI-Nutzer möchte ich hohe Scores und Analyseprobleme unterscheiden,
|
||
ohne fehlende Daten mit guter Qualität zu verwechseln.
|
||
|
||
@MC-019
|
||
Szenario: Der Standardmodus erstellt Reports ohne Score-bedingten Build-Abbruch
|
||
Angenommen die Analyse ist regulär abgeschlossen
|
||
Und eine Methode hat Mutation-CRAP 110
|
||
Und es ist kein Score-Gate aktiviert
|
||
Wenn das Ergebnis ausgegeben wird
|
||
Dann bleibt der Build wegen dieses Scores erfolgreich
|
||
Und der hohe Wert ist im Report sichtbar
|
||
|
||
@MC-020
|
||
Szenariogrundriss: Nur eine echte Überschreitung verletzt den Grenzwert
|
||
Angenommen eine Methode hat den gültigen Mutation-CRAP-Wert <score>
|
||
Und ein Score-Gate mit Grenzwert 30 ist aktiviert
|
||
Und es liegen keine weiteren Verstöße oder Analyseprobleme vor
|
||
Wenn das Gate ausgewertet wird
|
||
Dann ist das Build-Ergebnis <ergebnis>
|
||
|
||
Beispiele:
|
||
| score | ergebnis |
|
||
| 29 | erfolgreich |
|
||
| 30 | erfolgreich |
|
||
| 31 | fehlgeschlagen |
|
||
|
||
@MC-021
|
||
Szenario: Anzeigerundung beeinflusst das Gate nicht
|
||
Angenommen eine Methode hat Komplexität 10, 79 KILLED- und 21 SURVIVED-Ergebnisse
|
||
Und ihr exakter Mutation-CRAP-Wert beträgt 10.9261
|
||
Und für die Anzeige wird auf eine Nachkommastelle gerundet
|
||
Und der aktivierte Grenzwert beträgt 10.92
|
||
Wenn das Gate ausgewertet wird
|
||
Dann scheitert es wegen der tatsächlichen Überschreitung
|
||
Und der gerundete Anzeigewert 10.9 wird nicht für den Vergleich verwendet
|
||
|
||
@MC-022
|
||
Szenariogrundriss: Ein striktes Gate kann Analyseprobleme nicht als Erfolg werten
|
||
Angenommen alle numerisch bewerteten Methoden liegen unter ihrem Grenzwert
|
||
Aber es besteht <problem>
|
||
Wenn das aktivierte strikte Gate ausgewertet wird
|
||
Dann scheitert es mit einem konkreten Analysefehler
|
||
Und der Fehler wird nicht als schlechte Testqualität bezeichnet
|
||
|
||
Beispiele:
|
||
| problem |
|
||
| ein INCONCLUSIVE-Ergebnis |
|
||
| unerwartet fehlende Methodenkomplexität |
|
||
| ein unerwartet unvollständig inventarisierter Scope |
|
||
| ein fehlender oder unlesbarer aktueller Report |
|
||
| eine nicht unterstützte Report-Schemaversion |
|
||
|
||
@MC-023
|
||
Szenario: Eine leere Auswertung wird nicht stillschweigend grün
|
||
Angenommen ein Score-Gate ist aktiviert
|
||
Und im ausgewählten Scope ist keine einzige Methode numerisch bewertbar
|
||
Und leere Auswertungen sind nicht ausdrücklich erlaubt
|
||
Wenn das Gate ausgewertet wird
|
||
Dann scheitert es mit dem Hinweis auf eine leere Auswertung
|
||
|
||
@MC-024
|
||
Szenario: Ein absichtlich leeres Modul kann ausdrücklich erlaubt werden
|
||
Angenommen die Analyse eines Moduls ist regulär abgeschlossen
|
||
Und es gibt keine numerisch bewertbaren Methoden und keine Analysefehler
|
||
Und leere Auswertungen sind ausdrücklich erlaubt
|
||
Wenn das aktivierte Gate ausgewertet wird
|
||
Dann scheitert es nicht allein wegen der leeren Auswertung
|
||
Und der Report bezeichnet das Modul weiterhin als unbewertet
|
||
|
||
@MC-025
|
||
Szenario: Nach einer Grenzwertverletzung bleiben Reports verfügbar
|
||
Angenommen PIT und alle aktivierten Reporter sind regulär abgeschlossen
|
||
Und ein Methodenwert verletzt den aktivierten Grenzwert
|
||
Wenn der nachgeschaltete Gate-Task ausgeführt wird
|
||
Dann schlägt der Build fehl
|
||
Und der JSON-Report bleibt vollständig und schemakonform lesbar
|
||
Und der Markdown-Report und die normalen PIT-Reports bleiben verfügbar
|
||
|
||
@MC-026
|
||
Szenario: Maschinenlesbare Werte sind eindeutig und nachrechenbar
|
||
Angenommen eine Auswertung enthält bewertete und unbewertete Methoden
|
||
Wenn der JSON-Report geschrieben wird
|
||
Dann enthält er Metrikversion, Policykennung, Toolversionen und Analysescope
|
||
Und er enthält die verwendeten Methodenidentitäten und Status-Rohzähler
|
||
Und nicht definierte numerische Werte werden als null geschrieben
|
||
Und kein Feld enthält NaN oder Infinity
|
||
Und der Report entspricht seinem versionierten JSON-Schema
|
||
```
|
||
|
||
### 9.6 `06-gradle-integration.feature`
|
||
|
||
```gherkin
|
||
# language: de
|
||
Funktionalität: Das PIT-Plugin in Gradle-Projekten einsetzen
|
||
Als Java-Entwickler möchte ich meine vorhandene PIT-Konfiguration weiterverwenden,
|
||
statt Mutationstests für die neue Metrik separat orchestrieren zu müssen.
|
||
|
||
@MC-027
|
||
Szenario: Unit- und Integrationstests bleiben über PIT konfigurierbar
|
||
Angenommen ein Java-Projekt verwendet JUnit Jupiter
|
||
Und seine PIT-Konfiguration berücksichtigt Unit- und Integrationstest-Source-Sets
|
||
Und das Mutation-CRAP-Plugin ist aktiviert
|
||
Wenn der dokumentierte Mutation-CRAP-Workflow gestartet wird
|
||
Dann wird genau eine PIT-Analyse für diese Konfiguration angefordert
|
||
Und deren Ergebnisse einschließlich der einbezogenen Integrationstests werden verwendet
|
||
Und das Plugin startet keine zusätzlichen Gradle-Testtasks zur Komplexitätsermittlung
|
||
|
||
@MC-028
|
||
Szenario: Gleiche Methodenidentitäten aus zwei Teilprojekten bleiben getrennt
|
||
Angenommen zwei Gradle-Teilprojekte enthalten jeweils dieselbe JVM-Klasse und Methodensignatur
|
||
Und die beiden Methoden haben unterschiedliche Auswertungsergebnisse
|
||
Wenn beide Teilprojekte parallel ihre PIT-Analyse durchführen
|
||
Dann erhält jedes Teilprojekt seinen eigenen Report
|
||
Und die Einträge tragen unterscheidbare Analysekontexte
|
||
Und keine Ergebnisse oder Dateien werden gegenseitig überschrieben
|
||
|
||
@MC-029
|
||
Szenariogrundriss: Ein Anwender konsumiert das tatsächlich gepackte Plugin
|
||
Angenommen das Plugin wurde in ein isoliertes lokales Test-Artefakt-Repository publiziert
|
||
Und ein separates Anwenderprojekt verwendet <dsl>
|
||
Und es kennt keine Klassenverzeichnisse aus dem Plugin-Entwicklungsbuild
|
||
Wenn der dokumentierte Gradle/PIT-Aufruf gestartet wird
|
||
Dann wird die Service-Factory aus dem Plugin-JAR gefunden
|
||
Und alle erforderlichen Runtime-Abhängigkeiten werden geladen
|
||
Und ein Report mit echten Java-Methodenwerten entsteht
|
||
|
||
Beispiele:
|
||
| dsl |
|
||
| Kotlin DSL |
|
||
| Groovy DSL |
|
||
|
||
@MC-030
|
||
Szenario: Ein geänderter Grenzwert benötigt keine erneuten Mutationstests
|
||
Angenommen ein für unveränderte Analyseinputs gültiger PIT-Report liegt vor
|
||
Und die zugehörige PIT-Task kann korrekt als aktuell behandelt werden
|
||
Wenn nur der Gate-Grenzwert geändert und der Gate-Task ausgeführt wird
|
||
Dann wird die Gate-Entscheidung mit dem neuen Grenzwert neu berechnet
|
||
Und dafür wird keine zusätzliche PIT-Analyse gestartet
|
||
|
||
@MC-031
|
||
Szenario: Ein gescheiterter PIT-Lauf darf keinen alten Report als Erfolg verwenden
|
||
Angenommen ein erfolgreicher Report aus einem früheren Lauf existiert
|
||
Und die aktuelle PIT-Analyse scheitert vor dem regulären Abschluss
|
||
Wenn der dokumentierte CI-Workflow ausgeführt wird
|
||
Dann bleibt der Build fehlgeschlagen
|
||
Und es wird kein aktueller Gate-Erfolg aus dem alten Report abgeleitet
|
||
```
|
||
|
||
### 9.7 `07-kotlin-jvm.feature`
|
||
|
||
```gherkin
|
||
# language: de
|
||
@optional-kotlin
|
||
Funktionalität: Kotlin-JVM-Methoden ohne falsche Quelltextzusammenfassung auswerten
|
||
Als Kotlin-Nutzer möchte ich erkennen, welche tatsächlich erzeugten JVM-Methoden
|
||
mit der dokumentierten Compiler- und PIT-Kombination ausgewertet werden können.
|
||
|
||
@MC-032
|
||
Szenario: Gewöhnliche Kotlin-Methoden mit Verzweigungen auswerten
|
||
Angenommen ein Kotlin-JVM-Fixture enthält gewöhnliche überladene Methoden mit Verzweigungen
|
||
Und die gewählte PIT-Konfiguration erzeugt dafür auswertbare Mutanten
|
||
Wenn das Plugin die zugehörigen Originalklassen mit JaCoCo analysiert
|
||
Dann werden die Ergebnisse anhand von JVM-Klasse, Methodenname und Descriptor verbunden
|
||
Und die Überladungen erhalten getrennte nachvollziehbare Auswertungen
|
||
Und die verwendeten Kotlin-, PIT- und JaCoCo-Versionen sind dokumentiert
|
||
|
||
@MC-033
|
||
Szenario: Generierte Methoden nicht aufgrund gemeinsamer Quelltextzeilen zusammenfassen
|
||
Angenommen eine Kotlin-Quelltextfunktion erzeugt mehrere JVM-Methoden
|
||
Wenn das Plugin deren Komplexität und Mutationsergebnisse auswertet
|
||
Dann werden JVM-Methoden nicht allein aufgrund gemeinsamer Quelltextzeilen vereinigt
|
||
Und jede bewertete Methode hat eine nachweisbar passende Komplexität
|
||
Und nicht auswertbare oder ausdrücklich gefilterte Fälle werden mit Gründen gekennzeichnet
|
||
```
|
||
|
||
## 10. Quellen und Prüfhinweise
|
||
|
||
Recherchestand: **1. Oktober 2026**. Dies sind Primärquellen zu den verwendeten Erweiterungspunkten und Werkzeugen, keine Belege für die wissenschaftliche Validierung der neu definierten Metrik. Definitionen und Defaultentscheidungen in diesem Auftrag sind dort nicht automatisch vorgeschrieben.
|
||
|
||
Die Quellen wurden zur Spezifikation herangezogen; der beschriebene Plugin-Prototyp wurde im Rahmen der Dokumenterstellung **nicht implementiert oder ausgeführt**. Der Machbarkeitsnachweis bleibt deshalb ein ausdrücklicher erster Arbeitsauftrag.
|
||
|
||
**[S1] PIT — Advanced Usage / Plugins / Mutation Result Listener.** Service-Registrierung, Ausgabeformate, Tool-/Client-Classpath und Hinweise auf mögliche API-Änderungen.
|
||
<https://pitest.org/quickstart/advanced/>
|
||
|
||
**[S2] PIT — `MutationResultListenerFactory`.** Factory-Vertrag im untersuchten Entwicklungsstand. Am ausgewählten Release verifizieren.
|
||
<https://github.com/hcoles/pitest/blob/master/pitest-entry/src/main/java/org/pitest/mutationtest/MutationResultListenerFactory.java>
|
||
|
||
**[S3] PIT — Listener und klassenweise Ergebnisblöcke.** Insbesondere der ausdrückliche Hinweis, dass Ergebnisse derselben Klasse auf mehrere Instanzen verteilt sein können.
|
||
<https://github.com/hcoles/pitest/blob/master/pitest-entry/src/main/java/org/pitest/mutationtest/MutationResultListener.java>
|
||
<https://github.com/hcoles/pitest/blob/master/pitest-entry/src/main/java/org/pitest/mutationtest/ClassMutationResults.java>
|
||
|
||
**[S4] PIT — `ListenerArguments` und `SourceLocator`.** Verfügbare Listenerargumente sowie Quelltextzugriff, der nicht mit Bytecodezugriff verwechselt werden darf.
|
||
<https://github.com/hcoles/pitest/blob/master/pitest-entry/src/main/java/org/pitest/mutationtest/ListenerArguments.java>
|
||
<https://github.com/hcoles/pitest/blob/master/pitest-entry/src/main/java/org/pitest/mutationtest/SourceLocator.java>
|
||
|
||
**[S5] PIT — `ReportOptions`.** Kandidat für Classpath-/Codepath-Informationen; Nutzbarkeit und Kopplung an der gepinnten Version prüfen.
|
||
<https://github.com/hcoles/pitest/blob/master/pitest-entry/src/main/java/org/pitest/mutationtest/config/ReportOptions.java>
|
||
|
||
**[S6] JaCoCo — Analyzer-API und Implementierung.** Statische Analyse von Class-Dateien; die Implementierung behandelt fehlende Ausführungsdaten.
|
||
<https://www.jacoco.org/jacoco/trunk/doc/api/org/jacoco/core/analysis/Analyzer.html>
|
||
<https://www.jacoco.org/jacoco/trunk/coverage/org.jacoco.core/org.jacoco.core.analysis/Analyzer.java.html>
|
||
|
||
**[S7] JaCoCo — `IMethodCoverage` und `ICounter`.** JVM-Descriptor, Complexity-Counter und Gesamtanzahl.
|
||
<https://www.jacoco.org/jacoco/trunk/doc/api/org/jacoco/core/analysis/IMethodCoverage.html>
|
||
<https://www.jacoco.org/jacoco/trunk/doc/api/org/jacoco/core/analysis/ICounter.html>
|
||
|
||
**[S8] JaCoCo — Coverage Counters.** Zyklomatische Komplexität, fehlende Debuginformationen und Behandlung von Exception-Handling.
|
||
<https://www.jacoco.org/jacoco/trunk/doc/counters.html>
|
||
|
||
**[S9] Gradle-PIT-Plugin — offizielle Projektdokumentation.** Generische PIT-Plugins, Source-Sets, JUnit und Multi-Project-Builds. Versionsbeispiele der Webseite nicht ungeprüft übernehmen.
|
||
<https://gradle-pitest-plugin.solidsoft.info/>
|
||
|
||
**[S10] PIT — `Location`.** Klassenname, Methodenname und JVM-Methodendeskriptor.
|
||
<https://github.com/hcoles/pitest/blob/master/pitest/src/main/java/org/pitest/mutationtest/engine/Location.java>
|
||
|
||
**[S11] PIT — `DetectionStatus`.** Tatsächliche Statuswerte und deren `isDetected()`-Semantik. Am ausgewählten Release prüfen; nicht jede ältere Version enthält dieselben Enum-Werte.
|
||
<https://github.com/hcoles/pitest/blob/master/pitest/src/main/java/org/pitest/mutationtest/DetectionStatus.java>
|
||
|
||
**[S12] JaCoCo — Change History.** Insbesondere Änderungen an Filtern für Kotlin- und compilererzeugten Bytecode.
|
||
<https://www.jacoco.org/jacoco/trunk/doc/changes.html>
|
||
|
||
**[S13] PIT — Basic Concepts.** Bedeutung von Mutanten-Ergebnissen und nicht abgedeckten Mutanten.
|
||
<https://pitest.org/quickstart/basic_concepts/>
|
||
|
||
**[S14] PIT — Projektwebseite.** Abgrenzung zur erweiterten Sprach-/Framework-Unterstützung durch Arcmutate.
|
||
<https://pitest.org/>
|
||
|
||
**[S15] Cucumber — Gherkin Reference.** Features, Szenarien, Szenariogrundrisse, Beispiele, Tags und Sprachdeklaration.
|
||
<https://cucumber.io/docs/gherkin/reference/>
|
||
|
||
**[S16] Gradle — Testing Build Logic with TestKit.** Funktionstests für Gradle-Buildlogik mit separaten Anwenderprojekten.
|
||
<https://docs.gradle.org/current/userguide/test_kit.html>
|