Chạy lại lỗi kiểm tra đơn vị .NET từ tập lệnh PowerShell hoặc .NET


8

Các Visual Studio Kiểm tra nhiệm vụ trong Azure Devops có một tính năng thực sự mát mẻ, khả năng để thử lại các bài kiểm tra đơn vị đã thất bại. Đây là một tính năng tuyệt vời khi bạn có thời gian thử nghiệm dài và một số thử nghiệm không ổn định. Tác vụ thử nghiệm này trong Azure Devops hoạt động cho các nền tảng thử nghiệm khác nhau như xUnit, NUnit & MSTest. (Vì vậy, các bài kiểm tra viết cho .NET)

nhập mô tả hình ảnh ở đây

Nó sẽ có thể có được hành vi tương tự từ kịch bản? Tôi thích xUnit hoặc NUnit và chạy tập lệnh trong PowerShell.

Đối với xUnit có -method "name":

chạy một phương thức kiểm tra nhất định (có thể được chỉ định đầy đủ hoặc sử dụng ký tự đại diện; nghĩa là 'MyNamespace.MyClass.MyTestMethod' hoặc '* .MyTestMethod') nếu được chỉ định nhiều lần, hoạt động như một thao tác OR

NUnit có một nguồn--where=EXPRESSION cú pháp :

Một biểu thức chỉ ra các bài kiểm tra để chạy. Nó có thể chỉ định tên thử nghiệm, lớp, phương thức, danh mục hoặc thuộc tính so sánh chúng với giá trị thực với toán tử == ,! =, = ~ Và! ~. Xem Ngôn ngữ lựa chọn kiểm tra để biết mô tả đầy đủ về cú pháp.

Nhưng không chắc chắn làm thế nào để thu thập thử nghiệm thất bại cho xUnit hoặc NUnit để làm cho tất cả hoạt động.

Tất nhiên, sửa chữa bài kiểm tra dễ vỡ sẽ tốt hơn, nhưng điều đó đôi khi không dễ dàng.

Cập nhật: chạy từ. NET / C # (có thể được kích hoạt trong PowerShell) cũng được chấp nhận


Bạn có thể sử dụng Pester làm khung kiểm tra PowerShell.
Alex_P

Đó là cho các thử nghiệm trong PowerShell phải không? Đó không phải là trường hợp ở đây, các bài kiểm tra đơn vị được viết bằng C # /. NET
Julian

Nhưng không chắc chắn làm thế nào để thu thập thử nghiệm thất bại cho xUnit hoặc NUnit để làm cho tất cả hoạt động. Chỉ cần trên đỉnh đầu của tôi, có thể sử dụng một tùy chỉnh ITestLoggerWithParametersđể tạo một danh sách các tên thử nghiệm thất bại?
weichch

Vì vậy, bạn đi dotnet test --logger:customđể thu thập tên thử nghiệm thất bại.
weichch

Bạn chỉ muốn chạy các thử nghiệm thất bại của PowerShell hay bạn có thể chạy tất cả các thử nghiệm của PowerShell và sau đó chạy lại các thử nghiệm thất bại của PowerShell không? Bạn có thể cung cấp một ví dụ mã tối thiểu với hai bài kiểm tra (một lần thành công, một lần thất bại) không?
Thomas

Câu trả lời:


0

Bạn có thể thực hiện một chút "công việc thủ công" để có được kết quả bằng cách sử dụng các biểu thức thông thường trong powershell.

ví dụ là với XUnit. Vì vậy, những gì bạn phải làm là lưu trữ kết quả của dotnet test project.csprojmột biến. vì vậy một ví dụ sẽ giống như tiếp theo

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

như bạn có thể thấy có một số mẫu phổ biến mà chủ yếu là Error Messagecung cấp cho bạn gợi ý để biết nơi cần tìm, trong trường hợp này, xUnit chỉ ra các lỗi.X testname [{time}ms] Error Message

nếu bạn khớp văn bản đó với một biểu thức thông thường, bạn có thể nhận được phản hồi mong muốn: Tôi đã sử dụng văn bản này: X\s*(\S*)\s\[\d*ms\]\s*Error MessageTôi chắc chắn nó có thể được cải thiện (tôi không phải là bậc thầy về regex) nhưng nó thực hiện công việc của nó. bạn có thể loại bỏ Error Messageví dụ. Dù sao, tôi vẫn tiếp tục.

một khi bạn khớp kết quả, bạn chỉ cần lấy nhóm cho mỗi kết quả, trong trường hợp này tôi đã lưu nó vào TestName. và gọidotnet 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" 
}

dòng này $failedTestName = $failedTest.Groups['TestName'].Valuelà cần thiết, nếu bạn cố gắng để vượt qua .Groups..trong FullyQualifiedNamechuỗi, PowerShell hiểu chúng như là một chuỗi chữ.

bạn cần làm tương tự để tính thời gian và tỷ lệ phần trăm.

Ngoài ra đối với lần lặp đầu tiên thì dễ dàng hơn vì bạn có thể chạy tất cả các bài kiểm tra trong một lần, nhưng từ lần thứ hai trở đi bạn không thể. vì vậy danh sách cần thiết (để giữ các bài kiểm tra thất bại) là cần thiết.

một cái gì đó như thế này sẽ làm công việc

$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++
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.