Я пытаюсь изучить Appium и использовать его для тестирования приложений WPF. Тесты с калькулятором или блокнотом проходят нормально, но недавно я столкнулся с проблемой при попытке протестировать пользовательское приложение WPF.
Тесты настольного приложения Appium выдают исключение «Элемент не может быть расположен на странице с использованием заданных параметров поиска», но проходят без проблем, когда приложение запускается до запуска теста. Итак, я предполагаю, что моя фаза установки/инициализации как-то неверна, но я не знаю, почему.
Ошибка возникает, когда тест запускается без предварительного запуска приложения (поэтому, когда на этапе настройки необходимо запустить приложение). Тест проходит успешно, когда приложение запускается до запуска теста или даже если оно остается открытым после предыдущего неудачного запуска теста.
Запуск приложения занимает примерно 10-15 секунд, в течение которых сначала появляется слеш-скрин, а затем основное окно приложения.
В проекте используется nuget-пакет Appium.WebDriver версии 3.0.0.2.
Я пробовал Thread.Sleep в течение 30 секунд, но это не решает проблему.
[TestFixture]
public class DesktopAppSession
{
protected WindowsDriver<WindowsElement> _session;
protected const string WindowsApplicationDriverUrl = "http://127.0.0.1:4723";
protected const string AppId = @"<path to app.exe>";
[SetUp]
public void TestInit()
{
if (_session != null)
return;
var appCapabilities = new DesiredCapabilities();
appCapabilities.SetCapability("app", AppId);
appCapabilities.SetCapability("deviceName", "WindowsPC");
_session = new WindowsDriver<WindowsElement>(new Uri(WindowsApplicationDriverUrl), appCapabilities);
Assert.IsNotNull(_session);
Thread.Sleep(TimeSpan.FromSeconds(30));
_session.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
}
[TearDown]
public void TestCleanup()
{
if (_session != null)
{
_session.Quit();
_session = null;
}
}
[Test]
public void UserInfoModalShowsUp()
{
var userInfoButtonAName = "UserInfoButtonAName";
var userInfoButtonId = "UserInfoButtonAID";
var userInfoButton = _session.FindElementByAccessibilityId(userInfoButtonId);
Assert.True(userInfoButton != null);
userInfoButton.Click();
var userDetailsTitleLabel = _session.FindElementByName("User details");
userDetailsTitleLabel?.Click();
Assert.True(true);
}
}
Сообщение об исключении:
System.InvalidOperationException
HResult=0x80131509
Сообщение=Не удалось найти элемент на странице с заданными параметрами поиска.
Источник = веб-драйвер
Трассировки стека:
at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Ошибка ответаОтвет)
at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary2 parameters)
at OpenQA.Selenium.Remote.RemoteWebDriver.FindElement(String mechanism, String value)
at OpenQA.Selenium.Appium.AppiumDriver
1.FindElement(String by, String value)
Лог от WinAppDriver:
"POST /session/23293B57-F396-47CC-83EF-FCA491E269B0/элемент HTTP/1.1 Принять: приложение/json, изображение/png Длина контента: 56 Тип содержимого: приложение/json;charset=utf-8 Хост: 127.0.0.1:4723
{"использование":"идентификатор доступности","значение":"UserInfoButtonAID"} HTTP/1.1 404 не найден Длина контента: 139 Тип содержимого: приложение/json
{"статус":7,"значение":{"ошибка":"нет такого элемента","сообщение":"Не удалось найти элемент на странице с заданными параметрами поиска."}}"
Скорее всего, вам нужно будет переключить дескриптор окна на правильный.
Winappdriver использует оконные дескрипторы для окон верхнего уровня. Скорее всего, ваш экран-заставка будет окном верхнего уровня, и ваше фактическое приложение также будет окном верхнего уровня.
Таким образом, winappdriver будет иметь как минимум 2 дескриптора окна. Ваш драйвер (_session
в вашем случае) имеет свойство WindowHandles
, которое содержит список оконных дескрипторов. Эти дескрипторы добавляются в хронологическом порядке, поэтому самый последний дескриптор (из вашего приложения) должен быть последним дескриптором окна.
В этом примере показано, как переключать дескрипторы окна:
if (_session.CurrentWindowHandle != _session.WindowHandles.Last())
{
_session.SwitchTo().Window(_session.WindowHandles.Last());
}
Вы также можете проверить, есть ли у вас правильный дескриптор окна, проверив свойство источника страницы в вашем драйвере следующим образом: _session.PageSource;
. Источник страницы представляет собой xml-представление текущего выбранного дескриптора окна. Вы можете поместить его в часы Visual Studio и скопировать xml в служебную программу форматирования xml для удобочитаемости.
Дополнительную информацию о проблеме с заставкой и альтернативных способах ее устранения можно найти здесь. Обязательно проверьте ответы пользователя timotiusmargo.
Так было! Спасибо :) CurrentWindowHandle и дескриптор в WindowHandles имели разные значения. Раньше я проверял WindowHandles, но там был только один дескриптор, поэтому я предположил, что он должен быть таким же, как текущий, и на самом деле не проверял значения. В следующий раз постараюсь быть более тщательным. Еще раз спасибо :)