Files
werkcrappit/docs/features/04-pit-lifecycle.feature
miandmhoennig e31f44c1b4
werkator build succeeded after 01:34
werkator/publish build succeeded after 00:08
The progress of a PIT run in the log (0.15.0) (#26)
## The Problem

PIT writes nothing between its coverage analysis and its end.
Werkator's first full mutation run on 2026-10-03 took 2 h 24 min, and for more than two hours the log said nothing about how far it was.
The only way to tell was to count PIT's result objects in the heap of the running process with `jcmd`.

## Non-Goals

- An exact total: PIT's listener interface does not pass the number of mutants, and counting them would mean scanning the classes with PIT's mutation engine, work PIT does anyway.
- A remaining-time estimate: the last units of a run are often the slowest, so a rate from the first ones would mislead.

## The Scenarios

- `@MC-032` a progress line names classes, mutants of about the previous total, and the elapsed time; at most one line a minute.
- `@MC-033` without a finished previous report, or with an unreadable one, the line has no total, and nothing warns.
- `@MC-034` more mutants than in the previous run show that run's count instead of a percentage.
- `@MC-035` the end of the run always writes a last line with the final counts, before the summary.

##### Verified by

- [ProgressTest](../../werkcrappit-pit/src/test/java/de/javagil/werkcrappit/pit/report/ProgressTest.java)
- [MutationCrapListenerTest](../../werkcrappit-pit/src/test/java/de/javagil/werkcrappit/pit/listener/MutationCrapListenerTest.java) `progressEstimatesTheTotalFromThePreviousReport`, `progressWithoutTotalAfterAnUnfinishedRun`, `theConsoleGetsAFewLinesAndThePathToTheReports`

## The Solution

- `Progress` (package `report`) holds the counts and writes the lines; it knows no PIT type and takes the time as a parameter, so tests need no clock.
- The listener reads the previous `mutation-crap.json` in `runStart`, before it replaces it with the running marker.
  The total is the sum of the status counts and contradicted mutants of a `FINISHED` report.
  With time-stamped reports, each run writes its own directory, so there is no previous report.
- Mutants count distinctly, as the report counts them: `MutantAggregator.mutantCount()`.
  A class reported in several blocks counts once.
- The elapsed time counts from PIT's own start (`ListenerArguments.getStartTime()`), so it matches PIT's "Total".
- The plugin still only observes: it writes lines, nothing else.
- Version 0.15.0.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: mhoennig <michael@hoennig.de>
Reviewed-on: #26
2026-10-03 11:47:56 +02:00

88 lines
4.1 KiB
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
@MC-032
Szenario: Der Fortschritt eines langen PIT-Laufs steht im Log
Angenommen der vorige abgeschlossene Lauf hat 4368 Mutanten gemeldet
Und ein neuer PIT-Lauf mit dem Plugin läuft seit 1 Stunde, 12 Minuten und 5 Sekunden
Wenn PIT die Ergebnisse einer weiteren Klasse an das Plugin meldet
Und die letzte Fortschrittszeile ist mindestens eine Minute alt
Dann schreibt das Plugin die Zeile
"""
werkcrappit: 120 classes, 3104 of about 4368 mutants (71 %), 1:12:05
"""
Und kommen weitere Ergebnisse innerhalb dieser Minute, schreibt es keine Zeile
@MC-033
Szenario: Ohne abgeschlossenen vorigen Lauf zeigt der Fortschritt keine Gesamtzahl
Angenommen es gibt keinen vorigen Report, nur den Marker eines nicht beendeten Laufs oder einen unlesbaren
Wenn PIT die Ergebnisse einer Klasse an das Plugin meldet
Dann schreibt das Plugin die Zeile
"""
werkcrappit: 120 classes, 3104 mutants, 1:12:05
"""
Und ein unlesbarer voriger Report ist keine Warnung und bricht den Lauf nicht ab
@MC-034
Szenario: Mehr Mutanten als im vorigen Lauf übersteigen die Schätzung nicht sichtbar
Angenommen der vorige abgeschlossene Lauf hat 4368 Mutanten gemeldet
Wenn das Plugin bereits 4400 Mutanten gesehen hat
Dann schreibt das Plugin die Zeile
"""
werkcrappit: 250 classes, 4400 mutants (previous run: 4368), 2:20:41
"""
@MC-035
Szenario: Am Ende des Laufs steht immer eine letzte Fortschrittszeile
Angenommen ein PIT-Lauf mit dem Plugin hat 4368 Mutanten in 263 Klassen gemeldet
Und die letzte Fortschrittszeile ist weniger als eine Minute alt
Wenn PIT den Lauf beendet
Dann schreibt das Plugin vor seiner Zusammenfassung die Zeile
"""
werkcrappit: 263 classes, 4368 mutants, 2:23:31
"""