Retry flaky tests with dotnet test and PowerShell
At my current client, Nordic Leisure Travel Group , we have a large number of web tests that automates some of the QA effort. The tests are written in Selenium and Playwright. They run on a schedule in Jenkins and we get reports on email. They take quite some time to run. Unfortunately some of the tests are a bit flaky and it is hard to make them stable.
Therefore I set out trying to mitigate failed test runs by rerunning the failing tests.
A question/answer on Stack Overflow inspired me to write my own test script.
My requirements were:
- Use PowerShell
- Use the
dotnet test
CLI command - Keep track of failing tests and retry them
- Notify the test framework of the current retry iteration
- Make it possible to accept a certain percentage of failing tests
- Output the test result in a coherent way
This resulted in the following script:
- GitHub: test.ps1
- PowerShell Gallery: https://www.powershellgallery.com/packages/test-rerun
The script runs dotnet test
and uses the trx logger result file to collect failed tests.
Then reruns the failed tests and reports the final result.
Parameters
Path
- Path to the: project | solution | directory | dll | exe- Default value:
.
(current directory) - More info: dotnet test arguments
- Default value:
Configuration
- Build configuration for environment specificappsettings.json
file.- Default value:
Debug
- Valid values:
Debug
|Release
|Development
|Production
- Default value:
Filter
- Filter to run selected tests based on: TestCategory | Priority | Name | FullyQualifiedName- More info: Run selected unit tests
Settings
- Path to the.runsettings
file.Retries
- Number of retries for each failed test.- Default value:
2
- Valid range:
1-9
- Default value:
Percentage
- Required percentage of passed tests.- Default value:
100
- Valid range:
0-100
- Default value:
Examples
Run regression tests:
.\test.ps1 -filter "TestCategory=RegressionTest"
Run FooBar smoke tests in Development:
.\test.ps1 .\FooBar.Tests\FooBar.Tests.csproj -filter "TestCategory=SmokeTest" -configuration "Development"
Retry failed tests once and reports the run as green if 95% of the tests passed:
.\test.ps1 -retries 1 -percentage 95
Run tests configured with a .runsettings
file:
.\test.ps1 -settings .\test.runsettings
Output
If the tests passed, or the required percentage of tests passed, the script returns the exitcode 0
.
Otherwise the number of failed tests is returned as exitcode.
Output when successful:
Output when required percentage of tests passed:
Output when failed:
Showcase:
Tests
To showcase the test script I have written some tests in three popular frameworks.
The script and tests are available in this repo:
NUnit
- The
Category
attribute corresponds to theTestCategory
filter in the script. - The
Retry
parameter in theTestContext
contains the current retry iteration.
MSTest
- The
TestCategory
attribute corresponds to theTestCategory
filter in the script. - The
Retry
property in theTestContext
contains the current retry iteration.
XUnit
- The
Trait
attribute andTestCategory
parameter corresponds to theTestCategory
filter in the script. - XUnit does not support accessing TestRunParameters, so the current retry iteration is not available in this test framework.
Playwright
Playwright enables reliable end-to-end testing for modern web apps.
Web testing might be hard to get right and flaky tests can benefit from being retried.
Here is an example with Playwright and NUnit:
- The
SetUp
method starts a trace recording if the test is in retry mode. - The
TearDown
method exports the trace into a zip archive if the test failed.
The trace zip archives of failing tests can be examined at:
A .runsettings
file can be used to customizing Playwright options:
- More info: Using the .runsettings file
Run the Playwright tests with the .runsettings
file:
.\test.ps1 -filter FullyQualifiedName=ConductOfCode.PlaywrightTests -settings .\test.runsettings
Resources
- The test script and examples in this blog post: GitHub
- The test script: PowerShell Gallery
If you use Azure Pipelines consider using the Visual Studio Test v2 task with the rerunFailedTests
option: