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);