Как переделывать локаторы из XPath в UIAutomation?

К примеру, имею такой локатор XPath, как его переделать в UIAutomation локатор?
//UIAApplication[1]/UIAWindow[4]/UIAAlert[1]/UIAScrollView[1]/UIAStaticText[2]
Может быть это автоматизировано где-то?

К сожалению, пока не существует инструмента, который сделает это за Вас :slight_smile:
Вот ссылка на самый расширенный мануал по IosUIAutomation, который имеется в сети.
В Вашем случае это будет что-то типа:

.alerts()[0].scrollViews()[0].staticTexts()[1]

Также нужно сказать, что Ваш xpath - не особо хорош. Вы должны цепляться к каким-нибудь атрибутам элемента, а не сугубо к порядковым номерам. То же самое, и с IosUIAutomation. Тут вся суть в предикатах, которые применяются к атрибутам элемента.
Например:

.staticTexts().firstWithPredicate("name MATCHES 'YOU HAVE \d+ SKIPS LEFT'")

Если верить инструменту Automation на Mac OS, то он выглядит так:
.alert().scrollViews()[0].staticTexts()[1]
но ни так, ни так appium в тесте найти его не может.

А за предикаты спасибо, буду использовать.

Возможно. Попробуйте вообще без алертов, начиная со скролл вью.

.scrollViews()[0].staticTexts()[1]

Вы Аппиум-инспектором пользуетесь?

Аналогично не подошел.

Для поиска локаторов, да. Им и нашел xpath-локатор. В UIAuto-локаторы перевожу сам, проверяю в Instruments-Automation. Читал, что xpath-локаторы тормозят тесты.
Для запуска тестов использую Appium GUI.

В инспекторе тоже можно проверять локаторы IOSUIAutmation.

А можно посмотреть на разметку в XML (Copy XML)?

http://screencast.com/t/U8MXhrVh

Я не очень ему доверяю, половину реальных элементов не видит, если вводить корректный локатор ios UIAuto

Вы уверены, что даете ему правильный локатор?
Что у вас в других window элементах? Есть подозрение, что window с alert-ом - не основное, а Аппиум ищет только в основном окне приложения.
Если бы не русские символы в атрибуте name, я бы посоветовал найти по accesabilityId или name - “Email не найден”.

Попробуйте также такой локатор:

.elements().firstWithName("Authorization error").scrollViews()[0].staticTexts().firstWithPredicate("name BEGINSWITH "Email")

ага

По мимо аллерта еще окно авторизации и главный widow со всем функционалом.
Но по xpath-локатору же правильный элемент находится. Или Вы говорите про Appium Inspector?

так же не прошел.

Не подскажите, где можно найти такой локатор?

И еще, очень интересует вопрос, по каким локатором стоит искать элементы (для максимальной удобности и скорости тестов)? И правильно ли, допустим, искать все элементы только по ios uiautomation локаторам? У меня в наличии такие элементы как name, ios uiautomation и xpath.

accesabilityId - это и есть name для iOS.

В вашем случае:

WebElement element = driver.findElement(MobileBy.AccessibilityId("Email не найден"));

Но я не уверен, что Аппиум правильно отработает с кириллицей.

Аппиумовские локаторы немного отличаются от тех, что используются в IOS UIAutomation инструменте. В них, например, не применяются frontMostApp() и mainWindow(), а поиск начинается именно с главного окна. Я думаю, что проблема именно в этом.

По скорости работы локаторы можно упорядочить так:
id, name, AccessibilityId, className, IOSUIAutomation(AndroidUIAutomator), xpath

Написать правильный локатор без приложения практически нереально :slight_smile:
Проверьте отдельные части локатора в инспекторе и от этого уже отталкивайтесь.
Если находит

.elements().firstWithName("Authorization error")

или

.alerts()

значит алерт доступен и вы можете продолжить искать другие элементы в нем, дописывая локатор. Если нет попробуйте зайти с другой стороны:

.staticTexts().firstWithPredicate("name BEGINSWITH "Email")

Возможно, ваш текст будет сразу найден.

Если ни один из них не подошел, значит iOSUIAutomation неприменим в вашем случае.

какой тогда в нем смысл, если всегда можно использовать атрибут name?
Ведь, как я понял, accesabilityId и не будет без name?

огромное спасибо)

похоже только xpath)

Это необъяснимо, но иногда работает только один из них :slight_smile:
Кроме этого, AccessibilityId отлично подходит для мультиплатформенного тестирования - он доступен и для iOS, и для Android (в котором ему соответствует атрибут description). То есть вы можете иметь один локатор для двух платформ, что очень удобно.

В приведенном примере - UIAWindow[4]
Попробуйте: target.frontMostApp().windows()[3].alerts()[0].scrollViews()[0].staticTexts()[1]

так тоже не работает

странно, у меня такой подход работает без проблем, а что Аппиум при этом пишет в логах?

[debug] [UIAuto] Got result from instruments: {“status”:0,“value”:""}

[MJSONWP] Responding to client with driver.click() result: null
[HTTP] <-- POST /wd/hub/session/a08e1d2c-007a-4bc9-a608-7db41a95f50a/element/2/click 200 1312 ms - 76
[HTTP] --> POST /wd/hub/session/a08e1d2c-007a-4bc9-a608-7db41a95f50a/element {“using”:"-ios uiautomation",“value”:“target.frontMostApp().windows()[3].alerts()[0].scrollViews()[0].staticTexts()[1]”}
[MJSONWP] Calling AppiumDriver.findElement() with args: ["-ios uiautomation",“target.frontMostApp().windows()[3].alerts()[0].scrollViews()[0].staticTexts()[1]”,“a08e1d2c-007a-4bc9-a608-7db41a95f50a”]
[debug] [iOS] Executing iOS command ‘findElement’
[debug] [BaseDriver] Waiting up to 12000 ms for condition
[debug] [UIAuto] Sending command to instruments: au.getElementByUIAutomation(‘target.frontMostApp().windows()[3].alerts()[0].scrollViews()[0].staticTexts()[1]’)
[debug] [Instruments] [INST] 2016-05-05 14:34:52 +0000 Debug: evaluation finished
[debug] [Instruments] [INST] 2016-05-05 14:34:52 +0000 Debug: responding with:

[debug] [Instruments] [INST] 2016-05-05 14:34:52 +0000 Debug: Running system command #9: /Applications/Appium.app/Contents/Resources/node/bin/node /Applications/Appium.app/Contents/Resources/node_modules/appium/node_modules/appium-ios-driver/node_modules/appium-uiauto/build/lib/bin/command-proxy-client.js /var/folders/sv/fwvlgylj26z757f6hvjgvj3w0000gn/T/instruments_sock 2,{“status”:0,"v…

[debug] [Instruments] [INST] 2016-05-05 14:34:54 +0000 Debug: Got new command 9 from instruments: au.getElementByUIAutomation(‘target.frontMostApp().windows()[3].alerts()[0].scrollViews()[0].staticTexts()[1]’)

[debug] [Instruments] [INST] 2016-05-05 14:34:54 +0000 Debug: evaluating au.getElementByUIAutomation(‘target.frontMostApp().windows()[3].alerts()[0].scrollViews()[0].staticTexts()[1]’)

[debug] [Instruments] [INST] 2016-05-05 14:34:54 +0000 Debug: byUIAutomation: evaluating code: target.frontMostApp().windows()[3].alerts()[0].scrollViews()[0].staticTexts()[1]

[debug] [UIAuto] Socket data received (195 bytes)

[debug] [UIAuto] Got result from instruments: {“status”:17,“value”:“target.frontMostApp().windows()[3].alerts is not a function. (In ‘target.frontMostApp().windows()[3].alerts()’, ‘target.frontMostApp().windows()[3].alerts’ is undefined)”}

мда… Проблема в .alerts()[0], должно быть просто .alert()

[INST] 2016-05-06 07:16:38 +0000 Error: TypeError: target.frontMostApp().windows()[3].alert is not a function. (In 'target.frontMostApp().windows()[3].alert()', 'target.frontMostApp().windows()[3].alert' is undefined)

как последний вариант можно еще попробовать убрать windows()[3] из пути:
target.frontMostApp().alert().scrollViews()[0].staticTexts()[1]