WIP: Improve Appium test flakiness

This commit is contained in:
Ben Olden-Cooligan 2023-07-08 18:26:36 -07:00
parent 6e61e93f3e
commit 9b0f534dca
3 changed files with 33 additions and 41 deletions

View File

@ -1,3 +1,4 @@
using System.Linq.Expressions;
using System.Threading;
using NAPS2.App.Tests.Targets;
using NAPS2.Sdk.Tests;
@ -22,6 +23,7 @@ public class AppiumTests : ContextualTests
public void Init(IAppTestTarget target)
{
_session = StartSession(target.Gui, FolderPath);
ResetMainWindow();
}
public override void Dispose()
@ -37,32 +39,35 @@ public class AppiumTests : ContextualTests
base.Dispose();
}
protected void WaitUntilGone(string name, int timeoutInMs)
protected void ResetMainWindow()
{
_session.SwitchTo().Window(WaitFor(() => _session.WindowHandles.Single()));
}
protected T WaitFor<T>(Expression<Func<T>> expr, int timeoutInMs = 2000)
{
var func = expr.Compile();
var stopwatch = Stopwatch.StartNew();
try
while (true)
{
while (true)
try
{
if (_session.FindElementsByName(name).Count == 0)
var value = func();
if (value is null or false)
{
break;
throw new Exception();
}
return value;
}
catch (Exception)
{
if (stopwatch.ElapsedMilliseconds > timeoutInMs)
{
throw new WebDriverException("Timeout waiting for element to be gone");
throw new Exception($"Timed out waiting for \"{expr.Body}\"");
}
Thread.Sleep(100);
}
}
catch (InvalidOperationException)
{
}
}
protected void ResetMainWindow()
{
_session.SwitchTo().Window(_session.WindowHandles[0]);
}
protected void ClickAt(WindowsElement element)
@ -75,7 +80,7 @@ public class AppiumTests : ContextualTests
protected void ClickAtName(string name)
{
ClickAt(WaitAndFindElementByName(name));
ClickAt(WaitFor(() => _session.FindElementByName(name)));
}
protected void DoubleClickAt(WindowsElement element)
@ -89,23 +94,11 @@ public class AppiumTests : ContextualTests
protected void DoubleClickAtName(string name)
{
DoubleClickAt(WaitAndFindElementByName(name));
DoubleClickAt(WaitFor(() => _session.FindElementByName(name)));
}
protected WindowsElement WaitAndFindElementByName(string name)
protected bool HasElementWithName(string name)
{
int i = 0;
while(true)
{
try
{
return _session.FindElementByName(name);
}
catch (WebDriverException)
{
if (++i > 10) throw;
Thread.Sleep(100);
}
}
return _session.FindElementsByName(name).Count > 0;
}
}

View File

@ -34,14 +34,13 @@ public class ImportAndSaveTests : AppiumTests
ClickAtName("Save PDF");
ResetMainWindow();
var fileNameElements = _session.FindElementsByName("File name:");
var fileTextBox = fileNameElements.Last();
var fileTextBox = WaitFor(() => _session.FindElementsByName("File name:").Last());
ClickAt(fileTextBox);
fileTextBox.SendKeys("test.pdf");
ClickAtName("Save");
// Wait for the save to finish
Thread.Sleep(100);
WaitUntilGone("Cancel", 10_000);
WaitFor(() => !HasElementWithName("Cancel"), 10_000);
var path = Path.Combine(FolderPath, "test.pdf");
PdfAsserts.AssertImages(path,

View File

@ -26,17 +26,17 @@ public class ScanAndSaveTests : AppiumTests
// Click OK in the wia device dialog (selecting the first available device by default)
// TODO: More consistent way to pick the right OK button
ClickAt(_session.FindElementsByName("OK")[0]);
WaitUntilGone("Properties", 1_000);
WaitFor(() => !HasElementWithName("Properties"));
// Click OK in the profile settings window
ClickAtName("OK");
WaitFor(() => HasElementWithName("Cancel"));
// Wait for scanning to finish
WaitUntilGone("Cancel", 30_000);
WaitFor(() => !HasElementWithName("Cancel"), 30_000);
ResetMainWindow();
// Save "test.pdf" in the default location (which will be the test data path as NAPS2 knows we're in a test)^
ClickAtName("Save PDF");
ResetMainWindow();
var fileNameElements = _session.FindElementsByName("File name:");
var fileTextBox = fileNameElements.Last();
var fileTextBox = WaitFor(() => _session.FindElementsByName("File name:").Last());
ClickAt(fileTextBox);
fileTextBox.SendKeys("test.pdf");
ClickAtName("Save");
@ -62,17 +62,17 @@ public class ScanAndSaveTests : AppiumTests
if (!string.IsNullOrEmpty(deviceName)) ClickAtName(deviceName);
// Click Select in the twain device dialog (selecting the first available device by default)
ClickAtName("Select");
WaitUntilGone("Select", 1_000);
WaitFor(() => !HasElementWithName("Select"));
// Click OK in the profile settings window
ClickAtName("OK");
WaitFor(() => HasElementWithName("Cancel"));
// Wait for scanning to finish
WaitUntilGone("Cancel", 30_000);
WaitFor(() => !HasElementWithName("Cancel"), 30_000);
ResetMainWindow();
// Save "test.pdf" in the default location (which will be the test data path as NAPS2 knows we're in a test)^
ClickAtName("Save Images");
ResetMainWindow();
var fileNameElements = _session.FindElementsByName("File name:");
var fileTextBox = fileNameElements.Last();
var fileTextBox = WaitFor(() => _session.FindElementsByName("File name:").Last());
ClickAt(fileTextBox);
fileTextBox.SendKeys("test.jpg");
ClickAtName("Save");