Ein echter Lauf
Eine echte Änderung an Spectre.Console (Commit 01027ef), von der Coverage-Map bis zur Job Summary. Jede Ausgabe auf dieser Seite ist aus diesem Lauf kopiert, nicht von Hand geschrieben.
Die Änderung
Ein einzeiliges Refactoring im Widget Rule. Es ändert kein Verhalten, ist aber eine Codeänderung, daher würde eine normale Pipeline alle 787 Tests in 141 Klassen auf jedem Ziel-Framework ausführen.
// src/Spectre.Console/Widgets/Rule.cs, GetLineWithoutTitle
var text = border.GetPart(BoxBorderPart.Top).Repeat(maxWidth);
+var style = Style ?? Spectre.Console.Style.Plain;
return
[
- new Segment(text, Style ?? Spectre.Console.Style.Plain),
+ new Segment(text, style),
Segment.LineBreak
];
Der Lauf
Die Map wurde auf main mit td record aufgezeichnet. Der Pull Request führt dann aus:
$ td test --base main -- -f net10.0td: 1 changed file(s), 1 affected test project(s).Tests to run: filtered src/Spectre.Console.Tests/Spectre.Console.Tests.csproj (14 of 141 test class(es) run or reference the changed code, 0.6 s of 3.0 s (80% saved))Recorded test time: 0.6 s of 3.4 s (83% saved).Passed! - Failed: 0, Passed: 156, Skipped: 0, Total: 156 - Spectre.Console.Tests.dll (net10.0)td summary: passed src/Spectre.Console.Tests/Spectre.Console.Tests.csproj (14 class(es), 4.6 s)1 project(s) run, 0 failed, 0 skipped.Recorded test time: 0.6 s of 3.4 s (83% saved).
Es liefen 156 Tests in 14 Klassen statt 787 in 141. Das Projekt Spectre.Console.Ansi.Tests wurde nicht einmal gebaut: Nichts, wovon es abhängt, hat sich geändert.
Waren das die richtigen 14?
Zur Überprüfung haben wir GetLineWithoutTitle eine Ausnahme auslösen lassen und die gesamte Testsuite ausgeführt. Genau 14 Klassen schlugen fehl, und es sind die 14, die TestDetta ausgewählt hat: AlignTests+Center, +Left, +Right, CanvasTests, ColumnsTests, ExceptionTests, LayoutTests, PadderTests, PanelTests, RecorderTests, RowsTests, RuleTests, TableTests und TextPathTests. Die meisten davon erwähnen Rule nie: Sie erreichen es über Layouts und Panels, und genau das weiß die Coverage-Map, eine Namenssuche dagegen nicht.
Die Job Summary
Mit --summary-file "$GITHUB_STEP_SUMMARY" (die GitHub Action setzt es für Sie) erhält jeder Pull Request diese Zusammenfassung: was lief, warum jede Klasse lief und was übersprungen wurde.
TestDetta test selection
1 changed file(s) compared with main.
- 1 of 1 affected test project(s) ran, 0 skipped.
- Recorded test time: 0.6 s of 3.4 s (83% saved).
- All selected tests passed.
src/Spectre.Console.Tests/Spectre.Console.Tests.csproj: passed, 14 test class(es), recorded time 0.6 s of 3.0 s (80% saved)- why:
14 of 141 test class(es) run or reference the changed code - classes:
AlignTests+Center:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)AlignTests+Left:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)AlignTests+Right:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)CanvasTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)ColumnsTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)ExceptionTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)LayoutTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)PadderTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)PanelTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)RecorderTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)RowsTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)RuleTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)TableTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)TextPathTests:ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)
- skipped: 127 class(es) that ran none of the changed code and name none of it
- why:
Die Klassennamen sind hier gekürzt; die Zusammenfassung gibt sie vollständig aus (Spectre.Console.Tests.Unit.RuleTests).
Nach dem Warum fragen
Jede Entscheidung hat einen Grund, den Sie nachlesen können. -v schreibt die Spur nach stderr:
[DBG] CodeChangeDetector: src/Spectre.Console/Widgets/Rule.cs: Modified Spectre.Console.Rule GetLineWithoutTitle(RenderOptions,int)
[DBG] CodeChangeDetector: src/Spectre.Console/Widgets/Rule.cs: 1 changed symbol(s), affects whole project: False
[DBG] TestSelector: Spectre.Console.Rule GetLineWithoutTitle(RenderOptions,int) is affected because it changed
[DBG] TestSelector: Spectre.Console.Rule Render(RenderOptions,int) is affected because GetLineWithoutTitle
[DBG] TestSelector: Spectre.Console.Rule GetLineWithoutTitle(RenderOptions,int): test classes taken from coverage
Und --format json liefert die Entscheidung für jede Klasse, mit ihren Belegen und einer Zeitschätzung, für Skripte und Dashboards:
{
"project": "src/Spectre.Console.Tests/Spectre.Console.Tests.csproj",
"mode": "Filtered",
"reason": "14 of 141 test class(es) run or reference the changed code",
"estimate": {
"fullSeconds": 3,
"selectedSeconds": 0.6,
"savedSeconds": 2.4
},
"decisions": [
{
"class": "Spectre.Console.Tests.Unit.AlignTests+Center",
"selected": true,
"kind": "coverage",
"evidence": "ran Spectre.Console.Rule.GetLineWithoutTitle(RenderOptions,int), which changed (map 01027efcd6c4)"
},
{
"class": "Spectre.Console.Tests.PublicApiTests",
"selected": false,
"kind": "skipped",
"evidence": "ran none of the changed code and names none of it (map 01027efcd6c4)"
},
"…139 more"
]
}
Die Tests auf eigene Weise ausführen
td affected --format commands gibt den dotnet test-Aufruf aus, den TestDetta ausführen würde, sodass Sie ihn in Ihrem eigenen Skript verwenden können:
dotnet test src/Spectre.Console.Tests/Spectre.Console.Tests.csproj --filter 'FullyQualifiedName~Spectre.Console.Tests.Unit.AlignTests+Center.|FullyQualifiedName~Spectre.Console.Tests.Unit.AlignTests+Left.|FullyQualifiedName~Spectre.Console.Tests.Unit.AlignTests+Right.|FullyQualifiedName~Spectre.Console.Tests.Unit.CanvasTests.|FullyQualifiedName~Spectre.Console.Tests.Unit.ColumnsTests.|FullyQualifiedName~Spectre.Console.Tests.Unit.ExceptionTests.|FullyQualifiedName~Spectre.Console.Tests.Unit.LayoutTests.|FullyQualifiedName~Spectre.Console.Tests.Unit.PadderTests.|FullyQualifiedName~Spectre.Console.Tests.Unit.PanelTests.|FullyQualifiedName~Spectre.Console.Tests.Unit.RecorderTests.|FullyQualifiedName~Spectre.Console.Tests.Unit.RowsTests.|FullyQualifiedName~Spectre.Console.Tests.Unit.RuleTests.|FullyQualifiedName~Spectre.Console.Tests.Unit.TableTests.|FullyQualifiedName~Spectre.Console.Tests.Unit.TextPathTests.'
Über 40 Repositorys hinweg
Eine Änderung ist ein Datenpunkt. Im Evaluierungskorpus werden Member von 40 Open-Source-Bibliotheken einzeln geändert; bei einer Änderung an einem Member führte TestDetta im Median 28 % der Testklassen aus, in 18 der 40 Repositorys ein Viertel oder weniger. Bibliotheken, in denen fast jeder Test den Kern berührt (Scriban, Markdig), gewinnen wenig; geschichteter Code gewinnt am meisten. Jede fehlschlagende Klasse wurde mit der Auswahl abgeglichen: Bei 2,941 fehlschlagenden Änderungen wurden 3 übersehen, und jede davon wurde behoben.