RetryAttribute
Specifies that a test method should be rerun on failure up to the specified
maximum number of times.
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;
using System;
using System.Runtime.CompilerServices;
namespace NUnit.Framework
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class RetryAttribute : NUnitAttribute, IRepeatTest, ICommandWrapper
{
[System.Runtime.CompilerServices.Nullable(0)]
public class RetryCommand : DelegatingTestCommand
{
private readonly int _tryCount;
private readonly Type[] _retryExceptions;
public RetryCommand(TestCommand innerCommand, int tryCount)
: this(innerCommand, tryCount, Array.Empty<Type>())
{
}
public RetryCommand(TestCommand innerCommand, int tryCount, Type[] retryExceptions)
: base(innerCommand)
{
_tryCount = tryCount;
_retryExceptions = retryExceptions;
}
public override TestResult Execute(TestExecutionContext context)
{
int num = _tryCount;
while (num-- > 0) {
Exception ex = null;
try {
context.CurrentResult = innerCommand.Execute(context);
} catch (Exception exception) {
ex = exception.Unwrap();
if (context.CurrentResult == null)
context.CurrentResult = context.CurrentTest.MakeTestResult();
}
if (ex != null && !(ex is ResultStateException) && (num == 0 || !IsRetryException(ex))) {
context.CurrentResult.RecordException(ex);
break;
}
if (context.CurrentResult.ResultState != ResultState.Failure && !IsRetryException(context.CurrentResult.RecordedException))
break;
if (num > 0) {
context.CurrentResult = context.CurrentTest.MakeTestResult();
context.CurrentRepeatCount++;
}
}
return context.CurrentResult;
}
[System.Runtime.CompilerServices.NullableContext(2)]
private bool IsRetryException(Exception ex)
{
if (ex == null)
return false;
Type type = ex.GetType();
Type[] retryExceptions = _retryExceptions;
foreach (Type type2 in retryExceptions) {
if (type2.IsAssignableFrom(type))
return true;
}
return false;
}
}
private readonly int _tryCount;
public Type[] RetryExceptions { get; set; } = Array.Empty<Type>();
public RetryAttribute(int tryCount)
{
_tryCount = tryCount;
}
public TestCommand Wrap(TestCommand command)
{
return new RetryCommand(command, _tryCount, RetryExceptions);
}
}
}