codecharter coverage [root] [optionen]
codecharter coverage sucht die Testprojekte unterhalb von root
(standardmäßig das aktuelle Verzeichnis), führt sie mit Coverage-Messung aus,
führt die Ergebnisse zusammen und lässt den Build fehlschlagen, sobald die
Line-Coverage unter den geforderten Mindestwert fällt. Derselbe Lauf meldet
zusätzlich jede ungedeckte Region mit Quelltext-Ausschnitt, sodass Sie genau
sehen, welchen Zeilen ein Test fehlt.
Damit ist die zweite Hälfte des Quality Gates abgedeckt:
analyze beantwortet "ist der Code sauber
geschrieben", coverage beantwortet "ist er tatsächlich getestet".
Voraussetzung
Die Messung läuft über den Collector XPlat Code Coverage, der das Paket
coverlet.collector in jedem Testprojekt benötigt:
<PackageReference Include="coverlet.collector" Version="6.*" PrivateAssets="all" />
Ein Testprojekt ohne dieses Paket führt seine Tests zwar aus, liefert aber keine Coverage-Daten. Der Lauf benennt jedes betroffene Projekt und gibt die Zeile aus, die Sie ergänzen müssen.
Schnellstart
# Repository gegen den konfigurierten Mindestwert prüfen
codecharter coverage
# Einen Ordner gegen 90 % prüfen
codecharter coverage src --min-coverage 90
# Ergebnisse eines bereits gelaufenen Testlaufs auswerten
codecharter coverage --skip-tests
# Report in eine Datei statt nach stdout schreiben
codecharter coverage --output-file coverage-report.json
Der JSON-Report geht nach stdout, Diagnosen und eine einzeilige Zusammenfassung
nach stderr. Durch diese Trennung bleibt codecharter coverage > report.json
in einer Pipeline direkt verwendbar, ohne dass Sie etwas herausfiltern müssen.
Optionen
| Option | Standard | Beschreibung |
|---|---|---|
[root] |
aktuelles Verzeichnis | Verzeichnisbaum, der nach Testprojekten durchsucht wird. |
--min-coverage <prozent> |
aus der Konfiguration | Geforderte Mindest-Line-Coverage (0 bis 100). Überschreibt den konfigurierten Wert für diesen Lauf. Die Zahl wird gebietsschema-unabhängig gelesen, 99.5 ist also überall korrekt, 99,5 nicht. |
--results-root <verzeichnis> |
<root>/TestResults/coverage |
Ablage für Test- und Coverage-Artefakte. Ein relativer Pfad wird gegen das aktuelle Arbeitsverzeichnis aufgelöst, nicht gegen root. |
--skip-tests |
aus | Tests nicht ausführen, sondern die bereits vorhandenen Coverage-Dateien unterhalb des Results-Root auswerten. |
--output-file <pfad> |
stdout | JSON-Report in diese Datei schreiben. |
--verbose |
aus | Zusätzlich informative Fortschrittszeilen nach stderr ausgeben. |
--no-color |
aus | ANSI-Farbcodes abschalten. |
--skip-tests prüft vor der Auswertung, ob zu jedem gefundenen Testprojekt
eine Coverage-Datei vorliegt. Ein veralteter oder abgebrochener Lauf kann das
Gate so nicht unbemerkt passieren. Stammt das Ergebnisverzeichnis von einem
anderen Werkzeug und trägt nicht die Ablage je Projekt, fällt die Prüfung auf
einen Abgleich der Anzahlen zurück und weist darauf hin.
Konfiguration
Die Policy steht in .codecharter/config.yml, wird also einmal eingecheckt und
gilt für alle:
coverage:
minimum-percent: 99.5 # Schwelle des Gates (0 bis 100), Standard 100
snippet-context-lines: 3 # Kontextzeilen um jede ungedeckte Region
exclude: # von der Messung ausgenommene Dateien (Globs)
- "**/*.Designer.cs"
- "src/Generated/**"
Alle drei Schlüssel gelten repositoryweit. Anders als die Analyse-Sektionen
lässt sich coverage nicht pro Pfad-Scope variieren. Globs werden
groß-/kleinschreibungsgenau gegen Pfade relativ zum Lauf-Root abgeglichen,
geschrieben mit Schrägstrichen (**/ überspannt Verzeichnisse, * bleibt
innerhalb eines Pfadsegments).
Beachten Sie, dass coverage.exclude unabhängig vom übergeordneten exclude
der Analyse ist. Ein von der Regelanalyse ausgenommener Ordner verschwindet
also nicht stillschweigend aus Ihrer Coverage-Zahl, und umgekehrt.
Die wirksame Schwelle wird in dieser Reihenfolge bestimmt:
--min-coverageauf der Kommandozeile.codecharter/config.local.yml(Ihr persönliches, maschinenlokales Overlay).codecharter/config.yml(die eingecheckte Team-Einstellung)- der eingebaute Standardwert 100
Der Report nennt, welche der vier Quellen gewonnen hat, sodass sich ein
überraschendes Gate-Ergebnis immer zurückverfolgen lässt. Eine
coverage.exclude-Liste im lokalen Overlay ersetzt dabei die eingecheckte
Liste, sie ergänzt sie nicht.
All das lässt sich auch von der Kommandozeile aus pflegen statt von Hand, siehe codecharter config.
Was in die Zahl einfließt
Positional Records, die nur Daten tragen, enthalten kein Verhalten, das sich zu
testen lohnt, und bleiben deshalb außerhalb der Messung. Ein Record gilt so
lange als reiner Datenträger, wie kein Mitglied einen selbst geschriebenen
Rumpf hat: Auto-Properties (auch mit init) und der generierte
Primärkonstruktor erhalten diesen Status, während eine berechnete Property, ein
prüfender Konstruktor, ein Methodenrumpf, ein Operator, ein Indexer oder ein
Event den gesamten Record wieder in das Gate holen.
Klassen und Structs werden auf diesem Weg nie ausgenommen. Die Ausnahme ist bewusst auf Records beschränkt, weil nur ein Record den Vertrag "Daten, keine Logik" ausdrücklich erklärt.
Alles Weitere nehmen Sie selbst aus, über coverage.exclude.
Exit-Codes
| Code | Bedeutung |
|---|---|
0 |
Die Coverage hat den geforderten Mindestwert erreicht. |
1 |
Die Coverage liegt unter dem geforderten Mindestwert. |
2 |
Tests sind fehlgeschlagen oder die Coverage-Daten waren unvollständig. |
3 |
Überhaupt keine Coverage-Daten. |
64 |
Fehler in Aufruf, Konfiguration oder Umgebung (etwa ein fehlendes .NET SDK oder ein nicht beschreibbares --output-file). |
Das Gate ist fail-closed: fehlende, leere oder unlesbare Coverage-Daten führen
nie zu einem Erfolg. Exit-Code 3 bedeutet "es wurde nichts gemessen" und
erscheint niemals als grüne 100 %.
Die angezeigte Prozentzahl wird abgerundet. 100.00 % heißt also, dass
jede messbare Zeile gedeckt ist, und sonst nichts. Eine einzige ungedeckte
Zeile in einer großen Solution erscheint als 99.99 % und lässt ein Gate mit
100 % fehlschlagen, statt sich zu einem falschen Erfolg aufzurunden.
Der Report
Der JSON-Report besteht aus drei Teilen:
summary: messbare Zeilen, gedeckte Zeilen, der Prozentwert, der geforderte Mindestwert, dessen Herkunft, das Gate-Ergebnis und das Alter der ausgewerteten Coverage-Dateien.testResults: ein Eintrag je Testprojekt mit dessen Exit-Code (leer, wenn Sie--skip-testsverwenden).uncoveredRegions: jeder zusammenhängende Block nie ausgeführter Zeilen, mit Datei (als absoluter Pfad und relativ zum Lauf-Root), umgebender Methode, Zeilennummern und Quelltext-Ausschnitt.
Der relative Pfad ist der stabile Schlüssel für CI-Annotationen, denn er hängt nicht davon ab, wohin der Build-Agent das Repository ausgecheckt hat.
In der CI
- name: Coverage gate
run: codecharter coverage --output-file coverage-report.json
# Exit-Code 1 färbt den Schritt rot, sobald die Coverage unter den Mindestwert fällt.
Da die Schwelle in der Konfigurationsdatei steht, muss die Pipeline-Definition nicht angefasst werden, wenn das Team die Latte höher legt.
Mit einem KI-Assistenten
Dasselbe Gate steht KI-Coding-Assistenten als Tool run_coverage des
MCP-Servers zur Verfügung. Der Assistent erhält die
ungedeckten Regionen samt Datei, Methode, Zeilennummern und Ausschnitt, also
alles, was er braucht, um die fehlenden Tests zu schreiben, ohne vorher danach
zu suchen.
Weiterführend
- codecharter analyze für die Code-Qualitätshälfte des Gates.
- Konfigurationsdatei für die
coverage-Sektion im Zusammenhang. - Exit-Codes für die Exit-Codes der übrigen Befehle.