Kegagalan Pengujian UI - Tidak ada elemen maupun turunan yang memiliki fokus keyboard pada secureTextField

146

Ini kasus saya:

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

Kegagalan Pengujian UI - Tidak ada elemen maupun turunan yang memiliki fokus keyboard. Elemen:

Apa yang salah? Ini berfungsi dengan baik untuk normal textFields, tetapi masalah hanya muncul dengan secureTextFields. Ada solusi?

Bartłomiej Semańczyk
sumber
dan yang aneh adalah jika saya coba seperti ini bekerja XCUIApplication (). webViews.secureTextFields ["Password"]. tap () XCUIApplication (). webViews.secureTextFields ["Password"]. typeText ("Welcome")
aurilio
Mungkin Anda telah menyetel pengenal aksesibilitas tetapi Anda belum menyetel isAccessibilityElement = true
soumil
Saya telah menambahkan jawaban untuk pertanyaan serupa di sini: stackoverflow.com/a/59637897/2585413 . Masalah saya adalah bahwa saya memiliki UIWindows lain yang ada dengan nilai .windowLevel yang buruk
nteissler

Jawaban:

288

Masalah ini membuat saya sangat menderita, tetapi saya telah berhasil menemukan solusi yang tepat. Di Simulator, pastikan 'Hardware -> Keyboard -> Connect hardware keyboard' dimatikan.

Ted Kaminski
sumber
5
Ini telah memperbaiki masalah tersebut. Tetapi ini adalah solusi yang sangat buruk karena kami tidak dapat menerapkannya secara otomatis untuk CI.
Stanislav Pankevich
28
Jika Anda menjalankan pengujian pada CI (Jenkins dll.) Anda dapat menyetel parameter berikut dalam skrip sebelum menjalankan pengujian Anda. "default tulis com.apple.iphonesimulator ConnectHardwareKeyboard 0"
charlyatwork
7
Ini tidak menyelesaikan masalah bagi saya. Saya dapat dengan jelas melihat bidang teks mendapatkan fokus, dengan keyboard terbuka, tetapi kerangka pengujian tidak pernah dapat memasukkan teks menggunakan metode typeText:
Michael
2
Bekerja untuk saya di Xcode 11, tetapi menghapus centang Hubungkan keyboard perangkat keras mungkin tidak cukup. Seseorang juga harus memastikan bahwa keyboard perangkat lunak benar-benar ditampilkan (saya benar-benar memiliki situasi di mana tidak ada keyboard perangkat keras yang terhubung, dan tidak ada keyboard perangkat lunak yang ditampilkan, bahkan jika bidang teks memiliki fokus, dan kursor berkedip).
Reinhard Männer
2
Saya mengalami ini di Xcode 11 juga. Memperbaiki secara lokal, tetapi bagaimana ini dapat diatur di CI?
jherg
29

Baru-baru ini kami menemukan peretasan untuk membuat solusi dari jawaban yang diterima tetap ada. Untuk menonaktifkan pengaturan Simulator: 'Hardware -> Keyboard -> Connect hardware keyboard' dari baris perintah seseorang harus menulis:

defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0

Ini tidak akan memengaruhi simulator yang sedang berjalan - Anda perlu memulai ulang simulator atau memulai yang baru agar pengaturan tersebut memiliki efeknya.

AlexDenisov
sumber
ini tidak mengubah sesuatu.
netshark1000
@ netshark1000 yang dapat diubah dengan versi Xcode yang lebih baru, saya akan memeriksanya.
AlexDenisov
1
sangat membantu, saya membutuhkan kebalikan di mana keyboard selalu diaktifkan, tapi ya ini bagus, terima kasih. Saya akhirnya memilih defaults write com.apple.iphonesimulator ConnectHardwareKeyboard -bool true, tetapi konsepnya sama.
Laser Hawk
2
Saya membuat skrip pada fase build untuk melakukannya. Tapi saya perlu membunuh semua simulator, jadi saya melakukannya:killall "Simulator"; defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0;
Wagner Sales
Ini sepertinya tidak berfungsi lagi, apakah kuncinya sudah berubah ?? @AlexDenis
Simon McLoughlin
16

Saya telah menulis ekstensi kecil (Swift) yang berfungsi sempurna untuk saya. Ini kodenya:

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

Ide utamanya adalah tetap mengetuk elemen (bidang teks) sebelum keyboard disajikan.

berezhnyi oleksandr
sumber
Ini tidak berhasil untuk saya sekarang. Saya memiliki Xcode 7.2 (7C68), versi apa yang Anda miliki? Solusi yang kami temukan untuk CI ini berfungsi untuk kami: stackoverflow.com/a/34812979/598057 .
Stanislav Pankevich
Untuk mengkonfirmasinya sekali lagi: pembantu ini bekerja untuk Anda untuk bidang teks kata sandi aman bukan hanya bidang teks biasa?
Stanislav Pankevich
Ya, ini berfungsi untuk kedua jenis bidang teks: biasa dan aman.
berezhnyi oleksandr
1
Masalah dengan jawaban ini adalah ia menggunakan penundaan hardcode. Sebagai gantinya, gunakan model menunggu untuk ekspektasi dengan elemen keyboard.
pengguna1122069
12

Stanislav punya ide yang benar.

Dalam lingkungan tim, Anda membutuhkan sesuatu yang secara otomatis akan berfungsi. Saya menemukan perbaikan di sini di blog saya.

Pada dasarnya Anda hanya menempelkan:

UIPasteboard.generalPasteboard().string = "Their password"
let passwordSecureTextField = app.secureTextFields["password"]
passwordSecureTextField.pressForDuration(1.1)
app.menuItems["Paste"].tap()
RyanPliske
sumber
Terima kasih telah membagikan solusi Anda. Sayangnya itu tidak berfungsi untuk saya sekarang. Saya memiliki Xcode 7.2 (7C68), apa yang Anda? Lihat solusi lain yang kami temukan untuk CI: stackoverflow.com/questions/32184837/… .
Stanislav Pankevich
8

Penyebab lain kesalahan ini adalah jika ada tampilan induk bidang teks tempat Anda mencoba memasukkan teks yang disetel sebagai elemen aksesibilitas ( view.isAccessibilityElement = true). Dalam kasus ini, XCTest tidak bisa mendapatkan pegangan pada subview untuk memasukkan teks dan mengembalikan kesalahan.

Kegagalan Pengujian UI - Tidak ada elemen maupun turunan yang memiliki fokus keyboard.

Bukannya tidak ada elemen yang memiliki fokus (seperti yang sering Anda lihat pada keyboard dan kursor berkedip di UITextField), hanya saja tidak ada elemen yang dapat dijangkau yang memiliki fokus. Saya mengalami ini ketika mencoba memasukkan teks di UISearchBar. Bilah pencarian itu sendiri bukanlah bidang teks, saat menyetelnya sebagai elemen aksesibilitas, akses ke UITextField yang mendasarinya telah diblokir. Untuk mengatasi hal ini, searchBar.accessibilityIdentifier = "My Identifier"ditetapkan pada UISearchBarnamun isAccessibilityElementtidak ditetapkan true. Setelah ini, uji kode formulir:

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

Bekerja

pengguna3847320
sumber
7

Itu terjadi dengan saya berkali-kali. Anda harus menonaktifkan Perangkat Keras Keyboard dan Tata Letak yang Sama dengan OSX di Simulator Anda

Hardware / Keyboard (nonaktifkan semua)

Setelah itu, perangkat lunak keyboard tidak akan ditutup dan pengujian Anda dapat mengetik teks

Nonaktifkan Perangkat Keras

Fernando Martínez
sumber
5

Gunakan mode tidur antara meluncurkan aplikasi dan mengetik data di bidang teks seperti ini:

sleep(2)

Dalam kasus saya, saya terus mendapatkan kesalahan ini setiap saat dan hanya solusi ini yang membantu saya.

Kingalione
sumber
2
Masalahnya adalah jika Anda memiliki sejumlah besar Pengujian UI yang melakukan sesuatu seperti login awal, ini akan menambah biaya overhead yang besar untuk pengujian CI Anda.
delta2flat
5

Dalam kasus saya ini Hardware -> Keyboard -> Connect Hardware Keyboard-> Nonaktifkan tidak berhasil untuk saya.

Tapi saat aku mengikutinya

1) Hardware -> Keyboard -> Connect Hardware Keyboard-> Diaktifkan dan jalankan aplikasi
2) Hardware -> Keyboard -> Connect Hardware Keyboard-> Nonaktifkan .

Itu berhasil untuk saya

BharathRao
sumber
Bekerja untuk saya, MAN, saya benci aspek Xcode ini!
bwobbones
4

Ini mungkin membantu: Saya hanya menambahkan tindakan "ketuk" sebelum kesalahan; itu saja :)

[app.textFields[@"theTitle"] tap];
[app.textFields[@"theTitle"] typeText:@"kk"];
Carlos Peralta
sumber
2
Ini pasti tidak berfungsi untuk bidang teks kata sandi yang aman.
Stanislav Pankevich
Ini berfungsi untuk bidang teks kata sandi aman saya dengan baik. Solusi bagus.
Travis M.
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()
}
Anthony
sumber
4

Rekam case sesuka Anda, keyboard atau tanpa keyboard terpasang. Tapi lakukan hal berikut sebelum bermain tes.

Opsi berikut ini (sambungkan keyboard perangkat keras) harus dicentang saat memainkan tes.

masukkan deskripsi gambar di sini

umairhhhs
sumber
3

[ Memposting ulang komentar Bartłomiej Semańczyk sebagai jawaban karena itu memecahkan masalah saya]

Saya perlu melakukan Simulator> Atur Ulang Isi dan Pengaturan di bilah menu simulator agar ini mulai berfungsi untuk saya.

rogueleaderr
sumber
Mengatur ulang simulator juga membantu saya. Menariknya, masalahnya hanya terjadi di simulator sementara tes yang sama (tap texfield diikuti dengan mengetik karakter) berjalan dengan baik di perangkat.
Kristen
1

Terkadang bidang teks tidak diterapkan sebagai bidang teks, atau digabungkan ke dalam elemen UI lain dan tidak dapat diakses dengan mudah. Berikut cara melakukannya:

//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()       

Eugene Berezin
sumber
0

Baris pertama Anda hanyalah definisi kueri , yang tidak berarti itu passwordSecureTextFieldbenar-benar ada.

Baris kedua Anda akan secara dinamis menjalankan kueri dan mencoba mengikat (kembali) kueri ke elemen UI. Anda harus meletakkan breakpoint padanya dan memverifikasi bahwa satu dan hanya satu elemen yang ditemukan. Atau gunakan saja assert:

XCTAssertFalse(passwordSecureTextField.exists);

Jika tidak, tampilannya oke, tapharus memaksa keyboard terlihat dan kemudian typeTextberfungsi. Log kesalahan seharusnya memberi tahu Anda info lebih lanjut.

JOM
sumber
1
passwordSecureTextFieldada. Saya memperbaiki masalah, tetapi membersihkan memori, dan menulis ulang baris itu lagi. Aneh, tapi berhasil.
Bartłomiej Semańczyk
Senang mendengarnya sudah diperbaiki! Saya mengalami masalah serupa kemarin dengan beta 6 :)
JOM
beta 6? :-) benarkah? Saya hanya punya 5 :)
Bartłomiej Semańczyk
Anda sibuk membuat kode :) Beta 6 tidak merekam tapuntuk saya, butuh waktu untuk mengetahuinya. Praktik debug yang bagus!
JOM
Mungkin Anda tahu jawabannya untuk ini: stackoverflow.com/questions/32219015/… ?
Bartłomiej Semańczyk
0

Jangan mengacaukan, Ada masalah yang tertangkap karena Anda mencatat waktu pengujian aplikasi Anda akan menghubungkan keyboard perangkat keras sementara simulator waktu pengujian otomatis hanya membutuhkan keyboard perangkat lunak. jadi untuk cara memperbaiki masalah ini. Cukup gunakan keyboard perangkat lunak pada waktu perekaman Anda. Anda bisa melihat keajaiban.

codercat
sumber
0

Masalah bagi saya sama dengan Ted. Sebenarnya jika bidang kata sandi diketuk setelah bidang masuk dan KB perangkat keras aktif, keyboard perangkat lunak akan menutup dirinya sendiri pada ketukan bidang kedua, dan ini tidak khusus untuk tes UI.

Setelah beberapa waktu bermain-main dengan AppleScript, inilah yang saya hasilkan (peningkatan dipersilakan):

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

Buat file skrip dengan kode di atas dan tambahkan ke target yang diperlukan (mungkin hanya target tes UI, Anda mungkin ingin menambahkan skrip serupa ke target pengembangan Anda untuk mengaktifkan kembali keyboard HW selama pengembangan). Anda harus menambahkan Run Scriptfase dalam fase build dan menggunakannya seperti ini: osascript Path/To/Script/script_name.applescript

Timur Kuchkarov
sumber
0

Kami mengalami kesalahan yang sama saat menyetel accessibilityIdentifiernilai untuk tampilan kustom ( UIStackViewsubclass) yang berisi UIControlsubview. Dalam kasus tersebut XCTest tidak bisa mendapatkan fokus keyboard untuk elemen turunannya.

Solusi kami hanyalah menghapus accessibilityIdentifierdari tampilan induk kami dan mengatur accessibilityIdentifiersubview melalui properti khusus.

shadowhorst
sumber
0

Jawaban lain, tetapi bagi kami masalahnya adalah tampilan itu terlalu dekat dengan tampilan lain yang merupakan pengenal Gesture di atasnya. Kami menemukan bahwa kami memerlukan tampilan setidaknya 20 piksel (dalam kasus kami di bawah). Secara harfiah 15 tidak berhasil dan 20 atau lebih berhasil. Ini aneh saya akui, tetapi kami memiliki beberapa UITextView yang berfungsi dan beberapa tidak dan semuanya berada di bawah induk yang sama dan pemosisian lain yang identik (dan tentu saja nama variabel). Keyboard hidup atau mati atau apa pun tidak ada bedanya. Aksesibilitas menunjukkan bidang. Kami memulai ulang komputer kami. Kami melakukan clean build. Checkout sumber baru.

David J.
sumber
0

Saya mengalami masalah ini dan dapat memperbaikinya dalam skenario saya dengan mengambil solusi yang diposting oleh @AlexDenisov dan menambahkannya ke tindakan awal saya untuk menjalankan & menguji .

masukkan deskripsi gambar di sini

CodeBender
sumber
0

Tidak Perlu menyalakan / mematikan keyboard di I / O. Jangan gunakan .typeText untuk secureTextField, gunakan saja

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

Bonus: Anda mendapatkan suara keyboard klik :)

zdravko zdravkin
sumber
0

Akhirnya, saya menulis skrip yang mengedit file .plist Simulator dan menyetel ConnectHardwareKeyboardpropertinya ke false untuk simulator yang dipilih. Anda dengar itu benar, itu mengubah properti untuk simulator yang dipilih secara khusus di dalam kamus "DevicePreferences" daripada mengedit properti global.

Pertama, buat skrip shell bernama disable-hardware-keyboard.sh dengan konten berikut. Anda dapat menempatkannya di dalam "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

Sekarang ikuti langkah-langkah ini untuk memanggilnya dengan meneruskan udid simulator yang dipilih sebagai argumen:

  1. Edit skema Xcode Anda (atau tes UI skema tertentu jika Anda punya)
  2. Pergi ke: Tes> Tindakan sebelumnya
  3. Tambahkan skrip baru dengan mengetuk simbol "+"> "Tindakan Skrip Jalankan Baru".
  4. Penting: Di dalam menu drop-down "Berikan setelan build dari", pilih target aplikasi utama Anda, bukan target pengujian UI.
  5. Sekarang tambahkan skrip berikut di area teks di bawah.

Script di dalam Tes> Tindakan sebelumnya:

#!/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

Saatnya mengujinya:

  1. Luncurkan simulator
  2. Aktifkan keyboard perangkat keras untuk itu
  3. Jalankan pengujian UI apa pun dengan interaksi keyboard. Amati simulator mulai ulang dan keyboard perangkat keras dinonaktifkan. Dan interaksi keyboard tes berfungsi dengan baik. :)
Hasaan Ali
sumber
-1

Memiliki masalah yang sama dengan Securetextfields. Opsi menghubungkan perangkat keras di Simulator saya adalah, tetapi masih mengalami masalah. Akhirnya, ini berhasil untuk saya (Swift 3):

 let enterPasswordSecureTextField = app.secureTextFields["Enter Password"]
    enterPasswordSecureTextField.tap()
    enterPasswordSecureTextField.typeText("12345678")
Rads
sumber
1
Apa perbedaan antara kode Anda dan kode yang ditanyakan dalam pertanyaan.
Shivam Pokhriyal
-1

Yang memperbaiki masalah ini bagi saya adalah menambahkan tidur 1 detik:

let textField = app.textFields["identifier"]
textField.tap()
sleep(1)
textField.typeText(text)
Przemysław Wrzesiński
sumber