Невдача тестування користувальницького інтерфейсу - Ні один елемент, ні будь-який нащадок не мають фокусу клавіатури на secureTextField


139

Це мій випадок:

let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.tap()
passwordSecureTextField.typeText("wrong_password") //here is an error

Невдача тестування користувальницького інтерфейсу - Ні один елемент, ні будь-який нащадок не мають фокусу на клавіатурі. Елемент:

Що не так? Це нормально працює нормально textFields, але проблеми виникають лише з secureTextFields. Будь-які обходи?



і дивна частина - якщо я спробую так, це працює XCUIApplication (). webViews.secureTextFields ["Пароль"]. tap () XCUIApplication (). webViews.secureTextFields ["Пароль"]. typeText ("Ласкаво просимо")
aurilio

Можливо, ви встановили ідентифікатор доступності, але ви не встановили isAccessibilityElement = true
soumil

Тут я додав відповідь на подібне запитання: stackoverflow.com/a/59637897/2585413 . Моя проблема полягала в тому, що у мене існували інші UIWindows з поганими значеннями
.windowLevel

Відповіді:


264

Це питання викликало у мене біль болю, але мені вдалося знайти правильне рішення. У Симуляторі переконайтесь, що "Обладнання -> Клавіатура -> Підключити апаратну клавіатуру" вимкнено.


4
Це вирішило проблему. Але це дуже поганий спосіб вирішення, оскільки ми не можемо застосувати його автоматично для CI.
Станіслав Панькевич

25
Якщо ви запускаєте свої тести на CI (Jenkins тощо), ви можете встановити наступні параметри в скрипті перед запуском тестів. "за замовчуванням написати com.apple.iphonesimulator ConnectHardwareKeyboard 0"
charlyatwork

7
Це не вирішує проблему для мене. Я можу ясно бачити текстове поле отримання фокусу з клавіатурою вгору, але тестування рамки ніколи не може вводити текст з допомогою TypeText: метод
Michael

2
Працював для мене на Xcode 11, але зняти прапорець підключення апаратної клавіатури може бути недостатньо. Додатково потрібно переконатися, що клавіатура програмного забезпечення дійсно показана (у мене фактично була ситуація, коли не було підключено апаратну клавіатуру, і не було показано жодної програмної клавіатури, навіть якщо textField було зосереджено, а курсор блимав).
Рейнхард

1
Я наткнувся на це також на Xcode 11. Виправляється локально, але як це можна встановити в CI?
jherg

26

Нещодавно ми знайшли хак, щоб зробити рішення з прийнятої відповіді стійким. Щоб вимкнути налаштування Симулятора: 'Обладнання -> Клавіатура -> Підключити апаратну клавіатуру' з командного рядка слід написати:

defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0

Це не вплине на тренажер, який працює - вам потрібно перезапустити тренажер або запустити новий, щоб налаштування дала свій ефект.


це щось не змінило.
netshark1000

@ netshark1000, що може бути змінено з новою версією Xcode, я перевірю це.
АлексДенісов

1
надзвичайно корисно, мені потрібно було навпаки, коли клавіатура завжди включена, але так, це велике спасибі. Я закінчила свою справу defaults write com.apple.iphonesimulator ConnectHardwareKeyboard -bool true, але це та сама концепція.
Лазерний яструб

2
Я створив сценарій на фазах збірки, щоб це зробити. Але мені потрібно було вбити всі тренажери, тому я зробив це:killall "Simulator"; defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0;
продаж Вагнера

Схоже, це більше не працює, чи змінився ключ ?? @AlexDenisov
Simon McLoughlin

15

Я написав невелике розширення (Swift), яке ідеально підходить для мене. Ось код:

extension XCTestCase {

    func tapElementAndWaitForKeyboardToAppear(element: XCUIElement) {
        let keyboard = XCUIApplication().keyboards.element
        while (true) {
            element.tap()
            if keyboard.exists {
                break;
            }
            NSRunLoop.currentRunLoop().runUntilDate(NSDate(timeIntervalSinceNow: 0.5))
        }
    }
}

Основна ідея - тримати натискання на елемент (текстове поле) до появи клавіатури.


Зараз це для мене не працює. У мене Xcode 7.2 (7C68), яка у вас версія? Це рішення, яке ми знайшли для CI, працює для нас: stackoverflow.com/a/34812979/598057 .
Станіслав Панькевич

Щоб підтвердити це ще раз: цей помічник працює для вас для безпечного текстового поля пароля, а не просто звичайного текстового поля?
Станіслав Панькевич

Так, він працює для обох типів текстового поля: регулярного та безпечного.
Бережний Олександр

1
Проблема з цією відповіддю полягає в тому, що вона використовує жорстко кодовану затримку. Натомість використовуйте модель очікування очікування з елементом клавіатури.
користувач1122069

11

Станіслав має правильну ідею.

У командному середовищі вам потрібно щось, що автоматично працюватиме. Я придумав виправлення тут, у своєму блозі.

В основному ви просто вставте:

UIPasteboard.generalPasteboard().string = "Their password"
let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.pressForDuration(1.1)
app.menuItems["Paste"].tap()

Дякуємо, що поділилися своїм рішенням. На жаль, зараз це не працює для мене. У мене Xcode 7.2 (7C68), що ти? Дивіться інші рішення, для CI ми знайшли: stackoverflow.com/questions/32184837 / ... .
Станіслав Панкевич

8

Іншою причиною цієї помилки є те, що є батьківський вид текстового поля, в яке ви намагаєтеся ввести текст, який задається як елемент доступності ( view.isAccessibilityElement = true). У цьому випадку XCTest не в змозі отримати обробку підвідстежки для введення тексту та поверне помилку.

Невдача тестування користувальницького інтерфейсу - Ні один елемент, ні будь-який нащадок не мають фокусу на клавіатурі.

Справа не в тому, що жоден елемент не має фокусу (як часто ви можете бачити клавіатуру і миготливий курсор у UITextField), це просто той, що жоден елемент, до якого він може дійти, не має фокусу. Я зіткнувся з цим при спробі ввести текст у смужку пошуку UIS. Сама рядок пошуку не є текстовим полем, при встановленні її як елемента доступності було заблоковано доступ до базового UITextField. Щоб вирішити це, searchBar.accessibilityIdentifier = "My Identifier"було встановлено, UISearchBarоднак isAccessibilityElementне було встановлено true. Після цього тестуйте код форми:

app.otherElements["My Identifier"].tap()
app.otherElements["My Identifier"].typeText("sample text")

Працює


6

Зі мною траплялося багато разів. Потрібно відключити апаратне забезпечення клавіатури та таку ж макет як OSX у вашому симуляторі

Обладнання / клавіатура (відключити всі)

Після цього програмне забезпечення клавіатури не відхиляється, і ваші тести можуть вводити текст

Вимкнути обладнання


5

Використовуйте режим сну між запуском програми та введенням даних у такі текстові поля:

sleep(2)

У моєму випадку я щоразу отримував цю помилку, і тільки це рішення допомогло мені.


1
Проблема полягає в тому, що у вас є велика кількість тестів користувальницького інтерфейсу, які виконують щось на кшталт початкового входу, це додасть величезних накладних витрат до вашого тестового циклу CI.
delta2flat

4

Можливо, це допоможе: я просто додаю дію "tap" перед помилкою; це все :)

[app.textFields[@"theTitle"] tap];
[app.textFields[@"theTitle"] typeText:@"kk"];

2
Це безумовно не працює для безпечного текстового поля пароля.
Станіслав Панькевич

Це добре працювало в моєму безпечному текстовому полі пароля. Гарне рішення.
Травіс М.

4
func pasteTextFieldText(app:XCUIApplication, element:XCUIElement, value:String, clearText:Bool) {
    // Get the password into the pasteboard buffer
    UIPasteboard.generalPasteboard().string = value

    // Bring up the popup menu on the password field
    element.tap()

    if clearText {
        element.buttons["Clear text"].tap()
    }

    element.doubleTap()

    // Tap the Paste button to input the password
    app.menuItems["Paste"].tap()
}

4

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

Цю наступну опцію (підключення апаратної клавіатури) слід відмінити під час відтворення тесту.

введіть тут опис зображення


4

У моєму випадку це Hardware -> Keyboard -> Connect Hardware Keyboard-> Вимкнути не працював на мене.

Але коли я слідував

1) Hardware -> Keyboard -> Connect Hardware Keyboard-> Увімкнено та запустіть додаток
2) Hardware -> Keyboard -> Connect Hardware Keyboard-> Вимкнути .

Це працювало для мене


Працював для мене, MAN Я ненавиджу цей аспект XCode!
bwobbones

3

[ Репост Bartłomiej Semańczyk коментаря як відповідь, оскільки це вирішило для мене проблему]

Мені потрібно було зробити Simulator> Скинути зміст та параметри на панелі меню симулятора, щоб це почало працювати для мене.


Скидання тренажера мені теж допомогло. Цікаво, що проблема виникла лише в тренажері, коли той самий тест (натисніть текстове поле з наступним введенням символів) справно працював на пристрої.
Крістіан

1

Інколи текстові поля не реалізуються як текстові поля, або вони загорнуті в інший елемент інтерфейсу і не є легко доступними. Ось робота навколо:

//XCUIApplication().scrollViews.otherElements.staticTexts["Email"] the locator for the element
RegistrationScreenStep1of2.emailTextField.tap()
let keys = app.keys
 keys["p"].tap() //type the keys that you need
 
 //If you stored your data somewhere and need to access that string //you can cats your string to an array and then pass the index //number to key[]
 
 let newUserEmail = Array(newPatient.email())
 let password = Array(newPatient.password)
 
 //When you cast your string to an array the elements of the array //are Character so you would need to cast them into string otherwise //Xcode will compain. 
 
 let keys = app.keys
     keys[String(newUserEmail[0])].tap()
     keys[String(newUserEmail[1])].tap()
     keys[String(newUserEmail[2])].tap()
     keys[String(newUserEmail[3])].tap()
     keys[String(newUserEmail[4])].tap()
     keys[String(newUserEmail[5])].tap()       


0

Ваш перший рядок - це просто визначення запиту , що не означає, що passwordSecureTextFieldнасправді існувало б.

Ваш другий рядок буде динамічно виконувати запит і намагатиметься (повторно) прив’язати запит до елемента інтерфейсу. Ви повинні поставити на ньому точку перерви і переконатися, що знайдений один і лише один елемент. Або просто скористайтеся:

XCTAssertFalse(passwordSecureTextField.exists);

В іншому випадку це виглядає нормально, tapслід змусити клавіатуру видно, а потім typeTextпросто працювати. Журнал помилок повинен повідомити вам більше інформації.


1
passwordSecureTextFieldіснує. Я вирішив проблему, але очищаючи пам'ять, і знову переписав ці рядки. Дивно, але це спрацювало.
Bartłomiej Semańczyk

Приємно чути, що це виправлено! Я вчора
зіткнувся

бета-версія 6? :-) справді? У мене всього 5 :)
Bartłomiej Semańczyk

Ви були зайняті кодуванням :) Beta 6 не записувала tapдля мене, знадобилося певний час, щоб розібратися. Гарна практика налагодження!
JOM

Можливо, ви знаєте відповідь на це: stackoverflow.com/questions/32219015/… ?
Bartłomiej Semańczyk

0

Не заплутайтеся, там проблема спіймана - ви записуєте свій тестовий час, коли ваш додаток підключить апаратну клавіатуру, тоді як ваш симулятор автоматичного тестування часу займає лише клавіатуру програмного забезпечення. так як виправити ці проблеми. Просто використовуйте програмну клавіатуру на час запису. ви можете побачити магію.


0

Проблема для мене була такою ж, як і для Теда. Насправді, якщо поле пароля буде натиснуто після входу поля входу та апаратного КБ, клавіатура програмного забезпечення відхилить себе при натисканні другого поля, і це не характерно для тестів інтерфейсу користувача.

Через деякий час возитися з AppleScript, ось що я придумав (поліпшення вітаються):

tell application "Simulator" activate tell application "System Events" try tell process "Simulator" tell menu bar 1 tell menu bar item "Hardware" tell menu "Hardware" tell menu item "Keyboard" tell menu "Keyboard" set menuItem to menu item "Connect Hardware Keyboard" tell menu item "Connect Hardware Keyboard" set checkboxStatus to value of attribute "AXMenuItemMarkChar" of menuItem if checkboxStatus is equal to "✓" then click end if end tell end tell end tell end tell end tell end tell end tell on error tell application "System Preferences" activate set securityPane to pane id "com.apple.preference.security" tell securityPane to reveal anchor "Privacy_Accessibility" display dialog "Xcode needs Universal access to disable hardware keyboard during tests(otherwise tests may fail because of focus issues)" end tell end try end tell end tell

Створіть файл сценарію з кодом вище та додайте його до необхідних цілей (можливо, лише тести користувальницького інтерфейсу, ви можете додати подібний скрипт до своїх цілей розробки, щоб повторно включити HW-клавіатуру під час розробки). Ви повинні додати Run Scriptфазу збирання фаз і використовувати її так: osascript Path/To/Script/script_name.applescript


0

Ми зіткнулися з тією ж помилкою під час встановлення accessibilityIdentifierзначення для спеціального перегляду ( UIStackViewпідкласу), що містить UIControlпідперегляди. У цьому випадку XCTest не зміг отримати фокус на клавіатурі для спадкових елементів.

Нашим рішенням було просто вилучити accessibilityIdentifierз батьківського подання та встановити accessibilityIdentifierдля підпогляду за допомогою виділених властивостей.


0

Ще одна відповідь, але для нас проблема полягала в тому, що погляд був занадто близьким до іншого погляду, щоб в ньому розпізнавальник жестів. Ми виявили, що нам потрібен перегляд, що має бути не менше 20 пікселів (у нашому випадку нижче). Буквально 15 не працювали, а 20 і більше робили. Це дивно, я визнаю, але у нас були деякі UITextView, які працювали, а деякі - ні, і всі були під одним батьківським і однаковим іншим позиціонуванням (і назвами змінних, звичайно). Увімкнення або вимкнення клавіатури чи що завгодно не мало значення. Доступність показала поля. Ми перезапустили комп’ютери. Ми робили чисті будівлі. Свіжі каси джерела.



0

Я зіткнувся з цією проблемою і зміг її виправити за своїм сценарієм, взявши рішення, розміщене @AlexDenisov, і додавши його до моїх попередніх дій для запуску та тестування .

введіть тут опис зображення


0

Немає необхідності вмикати / вимикати клавіатуру вводу / виводу. Не використовуйте .typeText для secureTextField, просто використовуйте

app.keys["p"].tap()
app.keys["a"].tap()
app.keys["s"].tap()
app.keys["s"].tap()

Бонус: Ви отримуєте клацання звуку клавіатури :)


0

Нарешті, я написав сценарій, який редагує файл .plist симулятора та встановлює ConnectHardwareKeyboard властивість для вибраного симулятора. Ви правильно почули, він змінює властивість спеціально вибраного симулятора всередині словника "DevicePreferences", а не редагування глобальної властивості.

По-перше, створіть скрипт оболонки на ім’я disabled-hardware-keyboard.sh із наступним вмістом. Ви можете розмістити його в межах "YourProject / xyzUITests / Scripts /" .:

echo "Script: Set ConnectHardwareKeyboard to false for given Simulator UDID"

if [[ $1 != *-*-*-*-* ]]; then
    echo "Pass device udid as first argument."
    exit 1
else
    DEVICE_ID=$1
fi

DEVICE_PREFERENCES_VALUE='<dict><key>ConnectHardwareKeyboard</key><false/></dict>'
killall Simulator # kill restart the simulator to make the plist changes picked up
defaults write com.apple.iphonesimulator DevicePreferences -dict-add $DEVICE_ID $DEVICE_PREFERENCES_VALUE
open -a Simulator # IMPORTANT

Тепер виконайте ці дії, щоб викликати це, передаючи вибраний імітатор у вигляді аргументу:

  1. Відредагуйте свою схему Xcode (або певну схему тестів інтерфейсу користувача, якщо у вас є)
  2. Перейдіть до: Тест> Попередні дії
  3. Додайте новий сценарій, натиснувши символ "+"> "Новий запуск сценарію дії".
  4. Важливо: У спадному меню "Надати налаштування збірки з" виберіть основну ціль програми, а не ціль тестів інтерфейсу користувача.
  5. Тепер додайте наступний скрипт у текстову область нижче.

Сценарій всередині тесту> Попередні дії:

#!/bin/sh
# $PROJECT_DIR is path to your source project. This is provided when we select "Provide build settings from" to "AppTarget"
# $TARGET_DEVICE_IDENTIFIER is the UDID of the selected simulator
sh $PROJECT_DIR/xyzUITests/Scripts/disable-hardware-keyboard.sh $TARGET_DEVICE_IDENTIFIER

# In order to see output of above script, append following with it:
#  | tee ~/Desktop/ui-test-scheme-prescript.txt

Час тестувати:

  1. Запустіть тренажер
  2. Увімкніть апаратну клавіатуру для неї
  3. Запустіть будь-який тест на інтерфейс користувача із взаємодією з клавіатурою. Дотримуйтесь перезавантаження симулятора, а апаратна клавіатура відключена. І взаємодія клавіатури тесту працює чудово. :)

-1

Була така ж проблема із Securetextfields. Варіант підключення апаратного забезпечення в моєму симуляторі був, але все-таки зіткнувся з проблемою. Нарешті, це спрацювало для мене (Swift 3):

 let enterPasswordSecureTextField = app.secureTextFields["Enter Password"]
    enterPasswordSecureTextField.tap()
    enterPasswordSecureTextField.typeText("12345678")

Яка різниця між вашим кодом та кодом, заданим у запитанні.
Шивам Похріял
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.