Kullanıcı Arayüzü Test Hatası - Ne öğe ne de herhangi bir alt öğenin secureTextField üzerinde klavye odaklaması yoktur


139

Bu benim durumum:

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

Kullanıcı Arayüzü Test Hatası - Ne öğenin, ne de alt öğenin klavye odağı yoktur. element:

Yanlış olan ne? Bu normal için iyi çalışıyor textFields, ancak sorun sadece ile ortaya çıkıyor secureTextFields. Herhangi bir geçici çözüm var mı?



ve garip kısmı böyle denerseniz XCUIApplication () çalışır. webViews.secureTextFields ["Parola"]. tap () XCUIApplication (). webViews.secureTextFields ["Parola"]. typeText ("Welcome")
aurilio

Erişilebilirlik tanımlayıcısını ayarlamış olabilirsiniz, ancak isAccessibilityElement = true
soumil

Buraya benzer bir soruya bir cevap ekledim: stackoverflow.com/a/59637897/2585413 . Benim sorunum kötü .windowLevel değerleri ile var olan diğer UIWindows vardı
nteissler

Yanıtlar:


264

Bu sorun bana bir acı dünyasına neden oldu, ancak uygun bir çözüm bulmayı başardım. Simülatörde, 'Donanım -> Klavye -> Donanım klavyesini bağla'nın kapalı olduğundan emin olun.


4
Bu sorunu çözdü. Ancak, CI için otomatik olarak uygulayamadığımız için çok zayıf bir çözümdür.
Stanislav Pankevich

25
Testlerinizi CI'de (Jenkins vs.) çalıştırırsanız Testlerinizi çalıştırmadan önce bir komut dosyasında aşağıdaki parametreleri ayarlayabilirsiniz. "defaultults com.apple.iphonesimulator yazın ConnectHardwareKeyboard 0"
charlyatwork

7
Bu benim için problemi çözmüyor. Yöntemi: Açıkça textfield klavyesi kadar, odağın elde fakat test çerçeve TypeText kullanarak metin girmek asla görebilirsiniz
Michael

2
Benim için Xcode 11'de çalıştı, ancak Connect donanım klavyesinin işaretini kaldırmak yeterli olmayabilir. Biri ayrıca yazılım klavyesinin gerçekten gösterildiğinden emin olmak için var (textField odaklanmış ve imleç yanıp sönüyor olsa bile aslında hiçbir donanım klavyesinin bağlı olmadığı ve hiçbir yazılım klavyesi gösterilmiyordu).
Reinhard Männer

1
Ben de Xcode 11 ile karşılaştım. Yerel olarak düzelir, ancak bu CI'de nasıl ayarlanabilir?
jherg

26

Son zamanlarda kabul edilen cevabı kalıcı hale getirmek için bir hack bulduk. Simülatör ayarını devre dışı bırakmak için: 'Donanım -> Klavye -> Donanım klavyesini bağla' komut satırından şunu yazmalısınız:

defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0

Çalışan bir simülatörü etkilemez - simülatörün yeniden başlatılması veya bu ayarın etkili olması için yeni bir simülatör başlatmanız gerekir.


bu bir şeyi değiştirmedi.
netshark1000

@ netshark1000, Xcode'un yeni sürümüyle değiştirilebilecek, kontrol edeceğim.
AlexDenisov

1
son derece yararlı, klavyenin her zaman etkin olduğu tam tersine ihtiyacım vardı, ama evet bu harika teşekkürler. Sonunda devam ettim defaults write com.apple.iphonesimulator ConnectHardwareKeyboard -bool trueama aynı kavram.
Laser Hawk

2
Bunu yapmak için aşamalar üzerinde bir senaryo oluşturdum. Ama tüm simülatörleri öldürmem gerekiyordu, bu yüzden yaptım:killall "Simulator"; defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0;
Wagner Sales

Bu artık çalışmıyor gibi görünüyor, anahtar değişti ?? @AlexDenisov
Simon McLoughlin

15

Benim için mükemmel olan küçük bir uzantı (Swift) yazdım. İşte kod:

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

Ana fikir, klavye sunulmadan önce bir öğeye (metin alanı) dokunmaya devam etmektir.


Bu benim için çalışmıyor. Xcode 7.2 (7C68) kullanıyorum, hangi sürüme sahipsiniz? CI için bulduğumuz bu çözüm bizim için çalışıyor: stackoverflow.com/a/34812979/598057 .
Stanislav Pankevich

Bir kez daha onaylamak için: bu yardımcı sizin için sadece normal metin alanında değil güvenli şifre metin alanında da çalışır mı?
Stanislav Pankevich

Evet, her iki metin alanı türü için de çalışır: normal ve güvenli.
berezhnyi oleksandr

1
Bu cevapla ilgili sorun, kodlanmış bir gecikme kullanmasıdır. Bunun yerine klavye öğesiyle beklenti modelini kullanın.
user1122069

11

Stanislav doğru fikre sahip.

Bir ekip ortamında, otomatik olarak çalışacak bir şeye ihtiyacınız vardır. Burada blogumda bir düzeltme buldum.

Temelde sadece yapıştırın:

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

Çözümünüzü paylaştığınız için teşekkür ederiz. Ne yazık ki şu an benim için çalışmıyor. Xcode 7.2 (7C68) yaşıyorum, ya sen? CI için bulduğumuz diğer çözümlere bakın: stackoverflow.com/questions/32184837/… .
Stanislav Pankevich

8

Bu hatanın başka bir nedeni, erişilebilirlik öğesi ( view.isAccessibilityElement = true) olarak ayarlanmış metni girmeye çalıştığınız metin alanının üst görünümünün olmasıdır . Bu durumda, XCTest metni girmek için alt görünümde tanıtıcı alamaz ve hatayı döndürür.

Kullanıcı Arayüzü Test Hatası - Ne öğenin, ne de alt öğenin klavye odağı yoktur.

Hiçbir öğenin odağı olmadığı anlamına gelmez (genellikle UITextField'da klavyeyi yukarı ve yanıp sönen imleci görebildiğiniz gibi), ulaşamadığı hiçbir öğenin odaklanmamasıdır. Bir UISearchBar'a metin girmeye çalışırken buna rastladım. Arama çubuğunun kendisi metin alanı değildir, bir erişilebilirlik öğesi olarak ayarlandığında, temel UITextField öğesine erişim engellendi. Bu sorunu çözmek için, searchBar.accessibilityIdentifier = "My Identifier"tarihinde ayarlandı UISearchBarancak isAccessibilityElementayarlı değildi true. Bundan sonra, formun test kodu:

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

İşler


6

Benimle birçok kez oldu. Simülatörünüzde Klavye Donanımı ve OSX ile Aynı Düzeni devre dışı bırakmanız gerekir

Donanım / Klavye (tümünü devre dışı bırak)

Bundan sonra klavye yazılımı kapanmaz ve testleriniz metin yazabilir

Donanımı Devre Dışı Bırak


5

Uygulamayı başlatma ve bunun gibi metin alanlarına veri yazma arasında bir uyku kullanın:

sleep(2)

Benim durumumda her defasında bu hatayı almaya devam ediyordum ve sadece bu çözüm bana yardımcı oldu.


1
Sorun, ilk giriş gibi bir şey gerçekleştiren çok sayıda UI Testiniz varsa, bu CI test çalışmanıza büyük bir ek yük getirecektir.
delta2flat

4

Bu belki yardımcı olabilir: Ben sadece hatadan önce bir "musluk" eylem eklemek; bu kadar :)

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

2
Bu kesinlikle güvenli şifre metin alanı için çalışmaz.
Stanislav Pankevich

Bu benim güvenli şifre metin alanı için iyi çalıştı. Güzel çözüm.
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()
}

4

Klavyeyi veya klavyeyi takılı olmadan istediğiniz şekilde kaydedin. Ancak testi oynamadan önce aşağıdakileri yapın.

Test oynatılırken aşağıdaki seçenek (donanım klavyesini bağlayın) işaretlenmemiş olmalıdır.

resim açıklamasını buraya girin


4

Benim durumumda bu Hardware -> Keyboard -> Connect Hardware Keyboard-> Disable benim için çalışmadı.

Ama takip ettiğimde

1) Hardware -> Keyboard -> Connect Hardware Keyboard-> Etkin ve uygulamayı çalıştırın
2) Hardware -> Keyboard -> Connect Hardware Keyboard-> Devre dışı bırak .

Benim için çalıştı


Benim için çalıştı, MAN XCode'un bu yönünden nefret ediyorum!
bwobbones

3

[ Bartłomiej Semańczyk'in yorumunu bir cevap olarak geri bildirmek çünkü benim için problemi çözdü]

Benim için çalışmaya başlamak için simülatör menü çubuğunda Simülatör> İçeriği ve Ayarları Sıfırla yapmam gerekiyordu.


Simülatörü sıfırlamak da bana yardımcı oldu. İlginçtir ki sorun sadece simülatörde meydana geldi, aynı test (dokunma texfield ve ardından karakterleri yazarak) bir cihazda iyi çalıştı.
Christian

1

Bazen metin alanları metin alanları olarak uygulanmaz veya başka bir kullanıcı arayüzü öğesine sarılır ve kolayca erişilemez. İşte bir çözüm:

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

İlk satırınız yalnızca bir sorgu tanımıdır , bu passwordSecureTextFieldaslında var olacağı anlamına gelmez .

İkinci satırınız sorguyu dinamik olarak yürütür ve sorguyu UI öğesine (yeniden) bağlamaya çalışır. Üzerine bir kesme noktası koymalı ve bir ve yalnızca bir öğenin bulunduğunu doğrulamalısınız. Veya sadece bir iddia kullanın:

XCTAssertFalse(passwordSecureTextField.exists);

Aksi takdirde iyi görünüyor, tapklavyeyi görünür şekilde zorlamalı ve sonra typeTextçalışmalıdır. Hata günlüğü size daha fazla bilgi vermelidir.


1
passwordSecureTextFieldbulunmaktadır. Sorunu çözdüm, ancak belleği temizledim ve bu satırları tekrar yazdım. Tuhaf, ama işe yaradı.
Bartłomiej Semańczyk

Düzeltildiğini duymak güzel! Dün beta 6 ile benzer bir sorunla karşılaşıyorum :)
JOM

beta 6? :-) gerçekten mi? I have only 5 :)
Bartłomiej Semańczyk

Kodlamakla meşguldün :) Beta 6 tapbenim için kayıt yapmadı , anlaması biraz zaman aldı. İyi hata ayıklama uygulaması!
JOM

Belki bunun cevabını biliyorsunuzdur: stackoverflow.com/questions/32219015/… ?
Bartłomiej Semańczyk

0

Dağınık olmayın, sorun testinizin kaydedilmesinin nedeni, uygulamanızın donanım klavyesini bağlayacağı, otomatik test süresi simülatörünüzün sadece yazılım klavyesini alacağıdır. nasıl bu sorunları çözmek için. Kayıt sürenizde sadece yazılım klavyesini kullanın. sihri görebilirsiniz.


0

Benim için sorun Ted için olanla aynıydı. Aslında, giriş alanı ve donanım KB'si açıldıktan sonra şifre alanına dokunulursa, yazılım klavyesi ikinci alana dokunulduğunda kendini kapatır ve kullanıcı arayüzü testlerine özgü değildir.

AppleScript ile uğraştıktan bir süre sonra, işte ne buldum (iyileştirmeler hoş geldiniz):

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

Yukarıdaki kodu içeren bir komut dosyası oluşturun ve gerekli hedeflere ekleyin (muhtemelen yalnızca kullanıcı arayüzü testleri hedefi, geliştirme sırasında HW klavyeyi yeniden etkinleştirmek için geliştirme hedeflerinize benzer bir komut dosyası eklemek isteyebilirsiniz). Run ScriptDerleme aşamalarında faz eklemeli ve şu şekilde kullanmalısınız: osascript Path/To/Script/script_name.applescript


0

Alt accessibilityIdentifiergörünümler UIStackViewiçeren özel bir görünümün ( alt sınıf) değerini ayarlarken aynı hatayla karşılaştık UIControl. Bu durumda XCTest, azalan öğelerin klavye odağını alamadı.

Bizim çözümümüz, accessibilityIdentifierana görünümümüzden kaldırmak ve accessibilityIdentifierözel özellikler aracılığıyla alt görünümleri ayarlamaktı .


0

Başka bir cevap, ama bizim için sorun görünümü bir Hareket tanıyıcı üzerinde başka bir görünüme çok yakın oldu. Görünümün en az 20 piksel uzakta olması gerektiğine karar verdik (aşağıdaki örnekte). Kelimenin tam anlamıyla 15 işe yaramadı ve 20 veya daha fazlası işe yaradı. İtiraf edeceğim garip, ama çalışan bazı UITextViews vardı ve bazı değildi ve hepsi aynı ebeveyn ve özdeş diğer konumlandırma (ve tabii ki değişken isimleri) altında idi. Klavye açık veya kapalı ya da hiçbir fark yaratmamış. Erişilebilirlik alanları gösterdi. Bilgisayarlarımızı yeniden başlattık. Temiz yapılar yaptık. Taze kaynak kasaları.


0

Benim için bu sorunu çözen şey 1 saniyelik bir uyku eklemekti:

let textField = app.textFields["identifier"]
textField.tap()
sleep(1)
textField.typeText(text)

0

Bu sorunla karşılaştım ve @AlexDenisov tarafından gönderilen çözümü alıp çalışma ve test için ön işlemlerime ekleyerek senaryomda düzelttim .

resim açıklamasını buraya girin


0

G / Ç'de klavyeyi açıp kapatmaya gerek yoktur. SecureTextField için .typeText kullanmayın, sadece

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

Bonus: Klavye sesine tıklayabilirsiniz :)


0

Son olarak, Simulator'un .plist dosyasını ConnectHardwareKeyboarddüzenleyen ve seçilen simülatör için özelliği false olarak ayarlayan bir komut dosyası yazdım . Doğru duydunuz, genel özelliği düzenlemek yerine "DevicePreferences" sözlüğünde özel olarak seçilen simülatörün özelliğini değiştirir.

İlk olarak, aşağıdaki içeriklerle devre dışı- hardware-keyboard.sh adlı bir kabuk betiği oluşturun . "Projeniz / xyzUITests / Scripts /" içine yerleştirebilirsiniz.:

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

Şimdi seçilen simülatörün udid'ini argüman olarak geçirerek çağırmak için şu adımları izleyin:

  1. Xcode şemanızı düzenleyin (veya varsa UI testlerine özgü şema)
  2. Test> Ön işlemler
  3. "+" Sembolü> "Yeni Komut Dosyası Çalıştır'ı" na dokunarak yeni komut dosyası ekleyin.
  4. Önemli: İçinde "Oluşturma ayarlarını sağlayın" açılır menüsünde, kullanıcı arayüzü test hedefini değil ana uygulama hedefinizi seçin.
  5. Şimdi aşağıdaki komut dosyasını aşağıdaki metin alanına ekleyin.

Test içindeki komut dosyası> Ön eylemler:

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

Test etme zamanı:

  1. Başlat simülatörü
  2. Bunun için donanım klavyesini etkinleştir
  3. Klavye etkileşimi ile herhangi bir UI testi çalıştırın. Simülatörün yeniden başladığını ve donanım klavyesinin devre dışı olduğunu gözlemleyin . Ve testin klavye etkileşimi iyi çalışıyor. :)

-1

Securetextfields ile aynı sorunu vardı. Simülatörümdeki bağlantı donanımı seçeneği vardı, ancak yine de sorunla karşılaştı. Sonunda, bu benim için çalıştı (Swift 3):

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

Kodunuz ile soruda sorulan kod arasındaki fark nedir?
Shivam Pokhriyal
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.