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

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.

Anteil der pro Änderung ausgeführten Testklassen, nach Repository Runde 1 des Evaluierungskorpus: für jedes der 40 Repositorys der mittlere Anteil seiner Testklassen, den TestDetta bei einer Änderung an einem Member ausgewählt hat. Median 28 %. 0% 25% 50% 75% 100% opentelemetry-dotnet: im Mittel 6 % der Testklassen ausgeführt, über 79 fehlschlagende Änderungenopentelemetry-dotnet6% polly: im Mittel 7 % der Testklassen ausgeführt, über 65 fehlschlagende Änderungenpolly7% roslynator: im Mittel 8 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenroslynator8% spectre: im Mittel 9 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenspectre9% swashbuckle: im Mittel 12 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenswashbuckle12% nsec: im Mittel 13 % der Testklassen ausgeführt, über 79 fehlschlagende Änderungennsec13% aspnetcore-odata: im Mittel 13 % der Testklassen ausgeführt, über 79 fehlschlagende Änderungenaspnetcore-odata13% guardclauses: im Mittel 13 % der Testklassen ausgeführt, über 24 fehlschlagende Änderungenguardclauses13% mimekit: im Mittel 14 % der Testklassen ausgeführt, über 79 fehlschlagende Änderungenmimekit14% autofixture: im Mittel 16 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenautofixture16% communitytoolkit: im Mittel 18 % der Testklassen ausgeführt, über 76 fehlschlagende Änderungencommunitytoolkit18% libgit2sharp: im Mittel 19 % der Testklassen ausgeführt, über 57 fehlschlagende Änderungenlibgit2sharp19% castle-core: im Mittel 19 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungencastle-core19% serilog: im Mittel 20 % der Testklassen ausgeführt, über 79 fehlschlagende Änderungenserilog20% mediator: im Mittel 21 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenmediator21% fastendpoints: im Mittel 23 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenfastendpoints23% fluid: im Mittel 23 % der Testklassen ausgeführt, über 79 fehlschlagende Änderungenfluid23% carter: im Mittel 24 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungencarter24% lamar: im Mittel 26 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenlamar26% awesomeassertions: im Mittel 27 % der Testklassen ausgeführt, über 81 fehlschlagende Änderungenawesomeassertions27% nsubstitute: im Mittel 29 % der Testklassen ausgeführt, über 3 fehlschlagende Änderungennsubstitute29% immediate-handlers: im Mittel 29 % der Testklassen ausgeführt, über 43 fehlschlagende Änderungenimmediate-handlers29% open-xml-sdk: im Mittel 30 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenopen-xml-sdk30% fluentvalidation: im Mittel 32 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenfluentvalidation32% unitsnet: im Mittel 34 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenunitsnet34% vogen: im Mittel 36 % der Testklassen ausgeführt, über 77 fehlschlagende Änderungenvogen36% nodatime: im Mittel 43 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungennodatime43% graphql-dotnet: im Mittel 45 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungengraphql-dotnet45% newtonsoft-json: im Mittel 47 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungennewtonsoft-json47% autofac: im Mittel 49 % der Testklassen ausgeführt, über 77 fehlschlagende Änderungenautofac49% scrutor: im Mittel 57 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenscrutor57% meziantou-analyzer: im Mittel 63 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenmeziantou-analyzer63% automapper: im Mittel 67 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenautomapper67% protobuf-net: im Mittel 78 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenprotobuf-net78% yamldotnet: im Mittel 78 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenyamldotnet78% cliwrap: im Mittel 81 % der Testklassen ausgeführt, über 69 fehlschlagende Änderungencliwrap81% nlog: im Mittel 82 % der Testklassen ausgeführt, über 65 fehlschlagende Änderungennlog82% mapperly: im Mittel 89 % der Testklassen ausgeführt, über 79 fehlschlagende Änderungenmapperly89% markdig: im Mittel 98 % der Testklassen ausgeführt, über 80 fehlschlagende Änderungenmarkdig98% scriban: im Mittel 100 % der Testklassen ausgeführt, über 71 fehlschlagende Änderungenscriban100%
Mittlerer Anteil der pro Änderung ausgeführten Testklassen, Evaluierungsrunde 1. Fahren Sie mit der Maus über eine Zeile, um die Anzahl der zugrunde liegenden Änderungen zu sehen.