diff --git a/src/TestFramework/TestFramework/Attributes/TestMethod/DelayBackoffType.cs b/src/TestFramework/TestFramework/Attributes/TestMethod/DelayBackoffType.cs
new file mode 100644
index 0000000000..416d86b363
--- /dev/null
+++ b/src/TestFramework/TestFramework/Attributes/TestMethod/DelayBackoffType.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace Microsoft.VisualStudio.TestTools.UnitTesting;
+
+///
+/// Specifies a backoff type for the delay between retries.
+///
+public enum DelayBackoffType
+{
+ ///
+ /// Specifies a constant backoff type. Meaning the delay between retries is constant.
+ ///
+ Constant,
+
+ ///
+ /// Specifies an exponential backoff type.
+ /// The delay is calculated as the base delay * 2^(n-1) where n is the retry attempt.
+ /// For example, if the base delay is 1000ms, the delays will be 1000ms, 2000ms, 4000ms, 8000ms, etc.
+ ///
+ Exponential,
+}
diff --git a/src/TestFramework/TestFramework/Attributes/TestMethod/RetryAttribute.cs b/src/TestFramework/TestFramework/Attributes/TestMethod/RetryAttribute.cs
index 22008b44ed..f892961c45 100644
--- a/src/TestFramework/TestFramework/Attributes/TestMethod/RetryAttribute.cs
+++ b/src/TestFramework/TestFramework/Attributes/TestMethod/RetryAttribute.cs
@@ -3,17 +3,6 @@
namespace Microsoft.VisualStudio.TestTools.UnitTesting;
-public sealed class RetryResult
-{
- private readonly List _testResults = new();
-
- public void AddResult(TestResult[] testResults)
- => _testResults.Add(testResults);
-
- internal TestResult[]? TryGetLast()
- => _testResults.Count > 0 ? _testResults[_testResults.Count - 1] : null;
-}
-
///
/// This attribute is used to set a retry count on a test method in case of failure.
///
@@ -47,6 +36,20 @@ public RetryAttribute(int maxRetryAttempts)
///
public int MillisecondsDelayBetweenRetries { get; set; }
+ public DelayBackoffType BackoffType
+ {
+ get => field;
+ set
+ {
+ if (value is < DelayBackoffType.Constant or > DelayBackoffType.Exponential)
+ {
+ throw new ArgumentOutOfRangeException(nameof(value));
+ }
+
+ field = value;
+ }
+ }
+
///
/// Retries the test method times in case of failure.
/// Note that a first run of the method was already executed and failed before this method is called.
@@ -61,10 +64,15 @@ public RetryAttribute(int maxRetryAttempts)
protected internal virtual async Task ExecuteAsync(RetryContext retryContext)
{
var result = new RetryResult();
+ int currentDelay = MillisecondsDelayBetweenRetries;
for (int i = 0; i < MaxRetryAttempts; i++)
{
// The caller already executed the test once. So we need to do the delay here.
- await Task.Delay(MillisecondsDelayBetweenRetries);
+ await Task.Delay(currentDelay);
+ if (BackoffType == DelayBackoffType.Exponential)
+ {
+ currentDelay *= 2;
+ }
TestResult[] testResults = await retryContext.ExecuteTaskGetter();
result.AddResult(testResults);
diff --git a/src/TestFramework/TestFramework/Attributes/TestMethod/RetryResult.cs b/src/TestFramework/TestFramework/Attributes/TestMethod/RetryResult.cs
new file mode 100644
index 0000000000..7d1337450f
--- /dev/null
+++ b/src/TestFramework/TestFramework/Attributes/TestMethod/RetryResult.cs
@@ -0,0 +1,15 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+namespace Microsoft.VisualStudio.TestTools.UnitTesting;
+
+public sealed class RetryResult
+{
+ private readonly List _testResults = new();
+
+ public void AddResult(TestResult[] testResults)
+ => _testResults.Add(testResults);
+
+ internal TestResult[]? TryGetLast()
+ => _testResults.Count > 0 ? _testResults[_testResults.Count - 1] : null;
+}
diff --git a/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt b/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt
index 001d6f53fa..2d255084ba 100644
--- a/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt
+++ b/src/TestFramework/TestFramework/PublicAPI/PublicAPI.Unshipped.txt
@@ -190,6 +190,9 @@ Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertThrowsExactlyInterpola
Microsoft.VisualStudio.TestTools.UnitTesting.Assert.AssertThrowsExactlyInterpolatedStringHandler.AssertThrowsExactlyInterpolatedStringHandler(int literalLength, int formattedCount, System.Action! action, out bool shouldAppend) -> void
Microsoft.VisualStudio.TestTools.UnitTesting.DataRowAttribute.IgnoreMessage.get -> string?
Microsoft.VisualStudio.TestTools.UnitTesting.DataRowAttribute.IgnoreMessage.set -> void
+Microsoft.VisualStudio.TestTools.UnitTesting.DelayBackoffType
+Microsoft.VisualStudio.TestTools.UnitTesting.DelayBackoffType.Constant = 0 -> Microsoft.VisualStudio.TestTools.UnitTesting.DelayBackoffType
+Microsoft.VisualStudio.TestTools.UnitTesting.DelayBackoffType.Exponential = 1 -> Microsoft.VisualStudio.TestTools.UnitTesting.DelayBackoffType
Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataAttribute.DynamicDataAttribute(string! dynamicDataSourceName) -> void
Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataAttribute.DynamicDataAttribute(string! dynamicDataSourceName, Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataSourceType dynamicDataSourceType) -> void
Microsoft.VisualStudio.TestTools.UnitTesting.DynamicDataAttribute.DynamicDataAttribute(string! dynamicDataSourceName, System.Type! dynamicDataDeclaringType) -> void
@@ -203,6 +206,8 @@ Microsoft.VisualStudio.TestTools.UnitTesting.ITestDataSourceIgnoreCapability
Microsoft.VisualStudio.TestTools.UnitTesting.ITestDataSourceIgnoreCapability.IgnoreMessage.get -> string?
Microsoft.VisualStudio.TestTools.UnitTesting.ITestDataSourceIgnoreCapability.IgnoreMessage.set -> void
Microsoft.VisualStudio.TestTools.UnitTesting.RetryAttribute
+Microsoft.VisualStudio.TestTools.UnitTesting.RetryAttribute.BackoffType.get -> Microsoft.VisualStudio.TestTools.UnitTesting.DelayBackoffType
+Microsoft.VisualStudio.TestTools.UnitTesting.RetryAttribute.BackoffType.set -> void
Microsoft.VisualStudio.TestTools.UnitTesting.RetryAttribute.MaxRetryAttempts.get -> int
Microsoft.VisualStudio.TestTools.UnitTesting.RetryAttribute.MillisecondsDelayBetweenRetries.get -> int
Microsoft.VisualStudio.TestTools.UnitTesting.RetryAttribute.MillisecondsDelayBetweenRetries.set -> void