diff --git a/Lombiq.Tests.UI/Exceptions/VisualVerificationBaselineImageNotFoundException.cs b/Lombiq.Tests.UI/Exceptions/VisualVerificationBaselineImageNotFoundException.cs
index 6020c70a6..88507daa5 100644
--- a/Lombiq.Tests.UI/Exceptions/VisualVerificationBaselineImageNotFoundException.cs
+++ b/Lombiq.Tests.UI/Exceptions/VisualVerificationBaselineImageNotFoundException.cs
@@ -9,18 +9,18 @@ public class VisualVerificationBaselineImageNotFoundException : Exception
{
public VisualVerificationBaselineImageNotFoundException(
string path,
- int maxRetryCount,
+ bool isFinalTry,
Exception innerException = null)
- : base(GetExceptionMessage(path, maxRetryCount), innerException)
+ : base(GetExceptionMessage(path, isFinalTry), innerException)
{
}
- private static string GetExceptionMessage(string path, int maxRetryCount) =>
- maxRetryCount == 0 ? $"Baseline image file not found, thus it was created automatically under the path {path}."
- + " Please set its \"Build action\" to \"Embedded resource\" if you want to deploy a self-contained"
- + " (like a NuGet package) UI testing assembly. If you run the test again, this newly created verification"
- + " file will be asserted against and the assertion will pass (unless the display of the app changed in the"
- + " meantime)."
- : $"Baseline image file was not found under the path {path} and maxRetryCount is set to "
- + $"{maxRetryCount.ToTechnicalString()}, so it won't be generated. Set maxRetryCount to 0 to generate images.";
+ private static string GetExceptionMessage(string path, bool isFinalTry) =>
+ isFinalTry
+ ? $"Baseline image file not found, thus it was created automatically under the path {path}. Please set " +
+ $"its \"Build action\" to \"Embedded resource\" if you want to deploy a self-contained (like a NuGet " +
+ $"package) UI testing assembly. If you run the test again, this newly created verification file will " +
+ $"be asserted against and the assertion will pass (unless the display of the app changed in the " +
+ $"meantime)."
+ : $"Baseline image file was not found under the path {path} and this isn't the final try.";
}
diff --git a/Lombiq.Tests.UI/Extensions/VisualVerificationUITestContextExtensions.cs b/Lombiq.Tests.UI/Extensions/VisualVerificationUITestContextExtensions.cs
index 89a70938c..5e52c45bb 100644
--- a/Lombiq.Tests.UI/Extensions/VisualVerificationUITestContextExtensions.cs
+++ b/Lombiq.Tests.UI/Extensions/VisualVerificationUITestContextExtensions.cs
@@ -423,7 +423,7 @@ private static void AssertVisualVerificationApproved(
if (!File.Exists(approvedContext.BaselineImagePath))
{
- if (context.Configuration.MaxRetryCount == 0)
+ if (context.IsFinalTry)
{
context.SaveSuggestedImage(
element,
@@ -432,7 +432,7 @@ private static void AssertVisualVerificationApproved(
}
throw new VisualVerificationBaselineImageNotFoundException(
- approvedContext.BaselineImagePath, context.Configuration.MaxRetryCount);
+ approvedContext.BaselineImagePath, context.IsFinalTry);
}
baselineImage = Image.Load(approvedContext.BaselineImagePath);
diff --git a/Lombiq.Tests.UI/Services/UITestContext.cs b/Lombiq.Tests.UI/Services/UITestContext.cs
index 29c9fd4e1..9e995e954 100644
--- a/Lombiq.Tests.UI/Services/UITestContext.cs
+++ b/Lombiq.Tests.UI/Services/UITestContext.cs
@@ -21,6 +21,16 @@ public class UITestContext
///
public string Id { get; }
+ ///
+ /// Gets or sets the current retry count. This should only be edited from UITestExecutionSession.
+ ///
+ internal int RetryCount { get; set; }
+
+ ///
+ /// Gets a value indicating whether there may be further retries for this test.
+ ///
+ public bool IsFinalTry => RetryCount >= Configuration?.MaxRetryCount;
+
///
/// Gets data about the currently executing test.
///
diff --git a/Lombiq.Tests.UI/Services/UITestExecutionSession.cs b/Lombiq.Tests.UI/Services/UITestExecutionSession.cs
index 8327af530..ca53acdea 100644
--- a/Lombiq.Tests.UI/Services/UITestExecutionSession.cs
+++ b/Lombiq.Tests.UI/Services/UITestExecutionSession.cs
@@ -62,6 +62,8 @@ public async Task ExecuteAsync(int retryCount, string dumpRootPath)
{
var startTime = DateTime.UtcNow;
IDictionary failureDumpContainer = null;
+ // At this point _context may not exist yet.
+ if (_context != null) _context.RetryCount = retryCount;
_testOutputHelper.WriteLineTimestampedAndDebug("Starting execution of {0}.", _testManifest.Name);
@@ -108,6 +110,8 @@ public async Task ExecuteAsync(int retryCount, string dumpRootPath)
}
_context ??= await CreateContextAsync();
+ // At this point _context definitely exists, so ensure that RetryCount is set.
+ _context.RetryCount = retryCount;
_context.FailureDumpContainer.Clear();
failureDumpContainer = _context.FailureDumpContainer;
@@ -128,7 +132,7 @@ public async Task ExecuteAsync(int retryCount, string dumpRootPath)
await CreateFailureDumpAsync(ex, dumpRootPath, retryCount, failureDumpContainer);
- if (retryCount == _configuration.MaxRetryCount)
+ if (_context?.IsFinalTry == true || retryCount >= _configuration.MaxRetryCount)
{
var dumpFolderAbsolutePath = Path.Combine(AppContext.BaseDirectory, dumpRootPath);