Retry
RetryAttribute is used on a test method to specify that it should be rerun on failure up to a maximum number of times.
Constructor
RetryAttribute(int tryCount)
| Parameter | Type | Description |
|---|---|---|
tryCount |
int |
The maximum number of times the test should be run if it fails. This is the total number of attempts, not the number of retries after an initial failure. Therefore, [Retry(1)] does nothing and should not be used. |
Properties
| Property | Type | Description | Default |
|---|---|---|---|
RetryExceptions |
Type[] |
An array of exception types that trigger a retry when thrown. These are in addition to the normal behavior of retrying only on an assertion failure. | [] (empty array) |
Note
The RetryExceptions property was added in NUnit 4.5.0.
Applies To
| Test Methods | Test Fixtures (Classes) | Assembly |
|---|---|---|
| ✅ | ❌ | ❌ |
Example
[TestFixture]
public sealed class RetryTests
{
private readonly Random _random = new(42);
[Test]
[Retry(5)]
public async Task OperationShouldPassIn1s()
{
var sw = Stopwatch.StartNew();
string result = await ExpensiveOperation();
sw.Stop();
Assert.That(sw.ElapsedMilliseconds, Is.LessThan(1000), "Operation did not complete in time");
Assert.That(result, Is.Not.Null);
}
private async Task<string> ExpensiveOperation()
{
// Simulate an expensive operation
int duration = _random.Next(500, 1500);
await Task.Delay(duration); // Simulate work
return "Actual Result"; // Simulate a response
}
}
Using RetryExceptions
When you need to retry on specific exception types (such as TimeoutException or OperationCanceledException), you can set the RetryExceptions property:
[TestFixture]
public sealed class Retry
{
private int _delayInMilliseconds;
[OneTimeSetUp]
public void Setup()
{
_delayInMilliseconds = 2500;
}
[Test]
[Retry(5, RetryExceptions = [typeof(OperationCanceledException)])]
[CancelAfter(2000)]
public async Task QueryServiceAsync(CancellationToken cancellationToken)
{
string result = await CallExternalServiceAsync(cancellationToken);
Assert.That(result, Is.Not.Null);
}
private async Task<string> CallExternalServiceAsync(CancellationToken cancellationToken)
{
// Call an external service that may time out
int delayInMilliseconds = _delayInMilliseconds;
if (_delayInMilliseconds > 1000)
_delayInMilliseconds -= 1000; // Decrease delay for next attempt
await Task.Delay(delayInMilliseconds, cancellationToken); // Simulate a delay that may exceed
return "Actual Result"; // Simulate a response
}
}
Notes
- It is not currently possible to use
RetryAttributeon aTestFixtureor any other type of test suite. Only single test methods may be retried. - If a test has an unexpected exception, an error result is returned and it is not retried — unless that exception type is specified in the
RetryExceptionsproperty.