Führen Sie den .NET-Komponententest über das PowerShell-Skript oder .NET erneut aus

8

Die Visual Studio-Testaufgabe in Azure Devops bietet eine wirklich coole Funktion, nämlich die Möglichkeit, die fehlgeschlagenen Komponententests erneut zu versuchen . Dies ist eine großartige Funktion, wenn Sie eine lange Testzeit haben und einige Tests schuppig sind. Diese Testaufgabe in Azure Devops funktioniert für verschiedene Testplattformen wie xUnit, NUnit und MSTest. (Also Tests für .NET geschrieben)

Geben Sie hier die Bildbeschreibung ein

Wäre es möglich, dasselbe Verhalten aus dem Skript zu erhalten? Ich bevorzuge xUnit oder NUnit und führe das Skript in PowerShell aus.

Für xUnit gibt es ein -method "name":

Führen Sie eine bestimmte Testmethode aus (kann vollständig angegeben werden oder verwenden Sie einen Platzhalter, dh 'MyNamespace.MyClass.MyTestMethod' oder '* .MyTestMethod'), wenn sie mehrmals angegeben wird, und fungieren Sie als ODER-Operation

NUnit hat eine Syntaxquelle--where=EXPRESSION :

Ein Ausdruck, der angibt, welche Tests ausgeführt werden sollen. Es kann Testnamen, Klassen, Methoden, Kategorien oder Eigenschaften angeben, die sie mit tatsächlichen Werten mit den Operatoren == ,! =, = ~ Und! ~ Vergleichen. Eine vollständige Beschreibung der Syntax finden Sie unter Testauswahlsprache .

Sie sind sich jedoch nicht sicher, wie Sie den fehlgeschlagenen Test für xUnit oder NUnit erfassen sollen, damit alles funktioniert.

Natürlich wäre es besser, den Flockentest zu reparieren, aber das ist manchmal nicht so einfach.

Update: läuft ab. NET / C # (das in PowerShell ausgelöst werden könnte) ist ebenfalls akzeptabel

julianisch
quelle
Sie können Pester als PowerShell-Testframework verwenden.
Alex_P
Das ist für Tests in PowerShell nicht? Da dies hier nicht der Fall ist, sind die Unit-Tests in C # / geschrieben. NET
Julian
Sie sind sich jedoch nicht sicher, wie Sie den fehlgeschlagenen Test für xUnit oder NUnit erfassen sollen, damit alles funktioniert. Verwenden Sie vielleicht einen benutzerdefinierten Benutzer ITestLoggerWithParameters, um eine Liste der fehlgeschlagenen Testnamen zu erstellen.
weichch
Sie dotnet test --logger:customsammeln also fehlgeschlagene Testnamen.
weichch
Möchten Sie nur die fehlgeschlagenen Tests von PowerShell ausführen, oder ist es in Ordnung, alle Tests von PowerShell auszuführen und die fehlgeschlagenen Tests von PowerShell erneut auszuführen? Können Sie ein minimales Codebeispiel mit zwei Tests bereitstellen (einer erfolgreich, einer fehlgeschlagen)?
Thomas

Antworten:

0

Sie können ein wenig "manuelle Arbeit" leisten, um das Ergebnis mit regulären Ausdrücken in Powershell zu erhalten.

Das Beispiel ist mit XUnit. Sie müssen also das Ergebnis von dotnet test project.csprojin einer Variablen speichern . Ein Beispiel wird also wie das nächste sein

Test run for C:\Users\Tigrex\source\repos\ConsoleApp1\XUnitTestProject1\bin\Debug\netcoreapp2.2\XUnitTestProject1.dll(.NETCoreApp,Version=v2.2) Microsoft (R) Test Execution Command Line Tool Version 16.3.0 Copyright (c) Microsoft Corporation. All rights reserved. Starting test execution, please wait... A total of 1 test files matched the specified pattern. X XUnitTestProject1.UnitTest1.ThisIsAnotherFailedTestYesAgain [11ms] Error Message: Assert.Equal() Failure Expected: 2 Actual: 1 Stack Trace: at XUnitTestProject1.UnitTest1.ThisIsAnotherFailedTestYesAgain() in C:\Users\Tigrex\source\repos\ConsoleApp1\XUnitTestProject1\UnitTest1.cs:line 33 X XUnitTestProject1.UnitTest1.ThisIsAnotherFAiledTest [1ms] Error Message: Assert.Equal() Failure Expected: 2 Actual: 1 Stack Trace: at XUnitTestProject1.UnitTest1.ThisIsAnotherFAiledTest() in C:\Users\Tigrex\source\repos\ConsoleApp1\XUnitTestProject1\UnitTest1.cs:line 22 X XUnitTestProject1.UnitTest1.TestToFail [1ms] Error Message: Assert.Equal() Failure Expected: 2 Actual: 1 Stack Trace: at XUnitTestProject1.UnitTest1.TestToFail() in C:\Users\Tigrex\source\repos\ConsoleApp1\XUnitTestProject1\UnitTest1.cs:line 16 Total tests: 5 Passed: 2 Failed: 3 Total time: 1.2764 Seconds

Wie Sie sehen können, gibt es einige gängige Muster Error Message, die Ihnen hauptsächlich den Hinweis geben, wo Sie suchen müssen. In diesem Fall gibt xUnit die Fehlermuster anX testname [{time}ms] Error Message

Wenn Sie diesen Text mit einem regulären Ausdruck abgleichen, erhalten Sie die gewünschte Antwort: Ich habe diesen verwendet: X\s*(\S*)\s\[\d*ms\]\s*Error MessageIch bin sicher, dass er verbessert werden kann (ich bin kein Meister in Regex), aber er macht seinen Job. Sie können Error Messagezum Beispiel entfernen . Trotzdem mache ich weiter.

Sobald Sie mit dem Ergebnis übereinstimmen, müssen Sie nur noch die Gruppe für jedes Ergebnis abrufen, in dem ich sie gespeichert habe TestName. und rufen Sie diedotnet test ...

$result = dotnet test XUnitTestProject1/XUnitTestProject1.csproj 

$regex = 'X\s*(?<TestName>\S*)\s\[\d*ms\]\s*'

$matches = [regex]::Matches($result, $regex)
Foreach ($failedTest IN $matches)
{
    $failedTestName = $failedTest.Groups['TestName'].Value
   dotnet test --filter   "FullyQualifiedName=$failedTestName" 
}

Diese Zeile $failedTestName = $failedTest.Groups['TestName'].Valueist erforderlich, wenn Sie versuchen, die .Groups..in der FullyQualifiedNameZeichenfolge zu übergeben. PowerShell versteht sie als Literalzeichenfolge.

Sie müssen dasselbe tun, um die Zeiten und den Prozentsatz zu berechnen.

Auch für die erste Iteration ist es einfacher, weil Sie alle Tests auf einmal ausführen können, aber von der zweiten und weit können Sie nicht. Daher ist eine Liste erforderlich (um die fehlgeschlagenen Tests beizubehalten).

so etwas wird den Job machen.

$times = 1

$result = dotnet test XUnitTestProject1/XUnitTestProject1.csproj 
$regexFailedtests = 'X\s*(?<TestName>\S*)\s\[\d*ms\]\s*'
$FailedTestMatches = [regex]::Matches($result, $regexFailedtests)

$totalTestExecutedRegex = 'Total tests:\s*(?<TotalTest>\d*)'
$totalTests = [regex]::Matches($result, $totalTestExecutedRegex)[0].Groups['TotalTest'].Value -as [int]

$totalTesPassedRegex = 'Passed:\s*(?<Passed>\d*)'
$totalTestsPassed = [regex]::Matches($result, $totalTesPassedRegex)[0].Groups['Passed'].Value -as [int]


#convert the failed test into a list of string, so it can be looped.
$listFailedTest = New-Object Collections.Generic.List[string]
Foreach ($failedTest IN $FailedTestMatches)
{
    $failedTestName = $failedTest.Groups['TestName'].Value
    $listFailedTest.Add($failedTestName)
}

$percentage = ($totalTestsPassed*100)/$totalTests #Calculate the percentage

while($times -lt 5 -and $percentage -lt 70) {#5 loops or > 70% of test working

    $listFailedTestInsideDo = New-Object Collections.Generic.List[string]
    $listFailedTestInsideDo = $listFailedTest;  #do a copy of the main list
    $listFailedTest = New-Object Collections.Generic.List[string] ##empty the main list.
    Foreach ($failedTestName IN $listFailedTestInsideDo)
    {

       $result2 = dotnet test --filter   "FullyQualifiedName=$failedTestName" 

       if($result2 -match'Passed:\s*\d*') #if contains passed then it worked
       {
            totalTestsPassed++

        }else{
        $listFailedTest.Add($failedTestName) #add in new List for the new loop
       }
    }

    $percentage = ($totalTestsPassed*100)/$totalTests

    $times++
}
TiGreX
quelle