UIテストの失敗-要素も子孫も、secureTextFieldにキーボードフォーカスがない


138

これは私の場合です:

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

UIテストの失敗-要素も子孫もキーボードフォーカスを持っていません。素子:

なにが問題ですか?これは正常textFieldsに動作しますが、問題はでのみ発生しsecureTextFieldsます。回避策はありますか?



そして奇妙な部分は、私がこのようにしようとすると、XCUIApplication()。webViews.secureTextFields ["Password"]。tap()XCUIApplication()。webViews.secureTextFields ["Password"]。typeText( "Welcome")
aurilio

アクセシビリティ識別子を設定したが、isAccessibilityElement = trueを設定していない可能性があります
soumil

同様の質問への回答をここに追加しました:stackoverflow.com/a/59637897/2585413。私の問題は、.windowLevel値が不正な他のUIWindowsが存在していたことです
nteissler

回答:


264

この問題は私に苦痛の世界を引き起こしましたが、適切な解決策を理解することができました。シミュレーターで、「ハードウェア->キーボード->ハードウェアキーボードの接続」がオフになっていることを確認します。


4
これで問題が解決しました。ただし、CIに自動的に適用できないため、回避策としては非常に不十分です。
スタニスラフパンケビッチ

25
CI(Jenkinsなど)でテストを実行する場合、テストを実行する前に、スクリプトで次のパラメーターを設定できます。「デフォルトの書き込みcom.apple.iphonesimulator ConnectHardwareKeyboard 0 "
charlyatwork

7
これは私にとって問題を解決しません。キーボードを上にすると、テキストフィールドにフォーカスが移っているのがはっきりとわかりますが、テストフレームワークはtypeText:メソッドを使用してテキストを入力できません
Michael

2
Xcode 11で動作しましたが、[ ハードウェアキーボードの接続]をオフにしても十分ではない場合があります。さらに、ソフトウェアキーボードが実際に表示されることを確認する必要があります(実際には、textFieldにフォーカスがあり、カーソルが点滅していても、ハードウェアキーボードが接続されておらず、ソフトウェアキーボードが表示されていませんでした)。
ReinhardMänner、

1
Xcode 11でもこれに遭遇しました。ローカルで修正しますが、CIでこれをどのように設定できますか?
jherg

26

最近、受け入れられた回答からの解決策を永続化するハックを発見しました。シミュレーター設定を無効にするには、コマンドラインから「ハードウェア->キーボード->ハードウェアキーボードの接続」と入力します。

defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0

実行中のシミュレータには影響しません。設定を有効にするには、シミュレータを再起動するか、新しいシミュレータを起動する必要があります。


これは何かを変えていません。
netshark1000

新しいバージョンのXcodeで変更される可能性のある@ netshark1000を確認します。
AlexDenisov 2016年

1
非常に役に立ちました。キーボードが常に有効になっている反対のものが必要でしたが、ええ、これはとても感謝しています。結局はで行きまし defaults write com.apple.iphonesimulator ConnectHardwareKeyboard -bool trueたが、同じ概念です。
Laser Hawk

2
それを行うために、ビルドフェーズでスクリプトを作成しました。しかし、私はすべてのシミュレーターを殺す必要があったので、それを行いました:killall "Simulator"; defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0;
Wagner Sales

これはもう機能していないようです、キーが変更されましたか?@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
スタニスラフパンケビッチ

もう一度確認します。このヘルパーは、通常のテキストフィールドだけでなく、安全なパスワードテキストフィールドでも機能しますか?
スタニスラフパンケビッチ

はい、それは両方のタイプのテキストフィールドで機能します:通常および安全です。
berezhnyi oleksandr

1
この回答の問題は、ハードコードされた遅延を使用することです。代わりに、キーボード要素を使用した期待待機モデルを使用します。
user1122069

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はテキストを入力するためのサブビューのハンドルを取得できず、エラーを返します。

UIテストの失敗-要素も子孫もキーボードフォーカスを持っていません。

(UITextFieldでキーボードの上にカーソルが点滅しているのをよく見られるように)要素にフォーカスがないということではなく、到達できる要素フォーカスないというだけのことです。UISearchBarにテキストを入力しようとすると、これに遭遇しました。検索バー自体はテキストフィールドではありません。ユーザー補助要素として設定すると、基になる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
問題は、初期ログインのようなものを実行する多数のUIテストがある場合、CIテストの実行に大きなオーバーヘッドが追加されることです。
delta2flat 2017年

4

これは役立つかもしれません。エラーの前に「タップ」アクションを追加するだけです。それで全部です :)

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

2
これは間違いなく安全なパスワードテキストフィールドでは機能しません。
スタニスラフパンケビッチ

これは私の安全なパスワードのテキストフィールドでうまく機能しました。良い解決策。
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

キーボードまたはキーボードを接続せずに、必要に応じてケースを録音します。ただし、テストを行う前に次のことを行ってください。

この次のオプション(ハードウェアキーボードの接続)は、テストの再生中にオフにする必要があります。

ここに画像の説明を入力してください


4

私の場合、これはHardware -> Keyboard -> Connect Hardware Keyboard-> 無効にするはうまくませんでした。

しかし私がついたとき

1) Hardware -> Keyboard -> Connect Hardware Keyboard -> 有効にしてアプリを実行します
2)Hardware -> Keyboard -> Connect Hardware Keyboard-> 無効にします。

それは私のために働いた


私のために働いた、男私はXCodeのこの側面が嫌いです!
bwobbones

3

[ BartłomiejSemańczykの再投稿のコメントを回答として再投稿すると、問題が解決しました]

これを機能させるには、シミュレーターメニューバーで[シミュレーター]> [内容と設定をリセット]を実行する必要がありました。


シミュレーターをリセットすることも私に役立ちました。興味深いことに、同じテスト(texfieldをタップしてから文字を入力する)がデバイスで正常に実行されている間、問題はシミュレーターでのみ発生しました。
クリスチャン

1

テキストフィールドがテキストフィールドとして実装されていないか、別のUI要素にラップされていて簡単にアクセスできない場合があります。回避策は次のとおりです。

//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実際に存在するとは限りません。

2行目はクエリを動的に実行し、クエリをUI要素に(再)バインドしようとします。その上にブレークポイントを設定し、1つだけの要素が見つかったことを確認する必要があります。または単にアサートを使用します:

XCTAssertFalse(passwordSecureTextField.exists);

それ以外の場合は問題tapないように見え、キーボードを強制的に表示し、そのままtypeText動作するはずです。エラーログで詳細を確認できます。


1
passwordSecureTextField存在します。私は問題を修正しましたが、メモリを消去し、それらの行を再度書き直しました。奇妙ですが、うまくいきました。
パルトロミエSemańczyk

修正されてうれしいです!昨日、ベータ6で同様の問題に
遭遇しました

ベータ6?:-)本当に?私は5 :)持っている
パルトロミエSemańczyk

あなたはコーディングで忙しかった:) Beta 6はtap私のために記録しませんでした、それを理解するのにしばらく時間がかかりました。良いデバッグ練習!
JOM 2015

多分あなたはこれの答えを知っています:stackoverflow.com/questions/32219015/…
パルトロミエSemańczyk

0

失敗しないでください。自動テスト時間シミュレータがソフトウェアキーボードのみを使用しているときに、アプリがハードウェアキーボードに接続するテスト時間を記録していることが原因で問題が発生しました。この問題を修正する方法について。録音時間にソフトウェアキーボードを使用するだけです。あなたは魔法を見ることができます。


0

私にとっての問題は、テッドと同じでした。実際には、ログインフィールドの後にパスワードフィールドがタップされ、ハードウェアKBがオンの場合、ソフトウェアキーボードは2番目のフィールドタップでそれ自体を閉じます。これはUIテストに固有のものではありません。

しばらくして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

上記のコードを使用してスクリプトファイルを作成し、必要なターゲットに追加します(おそらくUIテストターゲットのみです。同様のスクリプトを開発ターゲットに追加して、開発中にHWキーボードを再度有効にすることができます)。Run Scriptビルドフェーズにフェーズを追加して、次のように使用する必要があります。 osascript Path/To/Script/script_name.applescript


0

サブビューを含むaccessibilityIdentifierカスタムビュー(UIStackViewサブクラス)の値を設定するときに、同じエラーが発生しましたUIControl。その場合、XCTestは子孫要素のキーボードフォーカスを取得できませんでした。

私たちの解決策はaccessibilityIdentifier、親ビューからを削除し、accessibilityIdentifier専用のプロパティを介してサブビューにを設定することでした。


0

別の答えですが、私たちにとっての問題は、ビューが別のビューに近すぎてジェスチャー認識機能がそれに対応できないことでした。ビューが少なくとも20ピクセル離れている必要があることがわかりました(以下の場合)。文字通り15は機能せず、20以上が機能しました。これは奇妙なことですが、機能しているUITextViewsと機能していないUITextViewsがあり、それらはすべて同じ親の下にあり、他の同じ位置付け(そしてもちろん変数名)でした。キーボードのオン/オフなど、違いはありませんでした。アクセシビリティはフィールドを示しました。コンピュータを再起動しました。クリーンビルドを行いました。新鮮なソースのチェックアウト。


0

この問題を解決したのは、1秒の睡眠を追加することでした。

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

0

私はこの問題に遭遇し、@ AlexDenisovによって投稿された解決策を取り、それを実行およびテスト用の事前アクションに追加することにより、私のシナリオでそれを修正することができました。

ここに画像の説明を入力してください


0

I / Oでキーボードのオン/オフを切り替える必要はありません。secureTextFieldに.typeTextを使用しないでください。

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

ボーナス:キーボードの音をクリックしてください:)


0

最後に、シミュレーターの.plistファイルを編集して、 ConnectHardwareKeyboardし、選択したシミュレータのプロパティをfalseに。正しく聞こえました。グローバルプロパティを編集するのではなく、「DevicePreferences」ディクショナリ内の特定のシミュレータのプロパティを変更します。

まず、次の内容でdisable-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

次の手順に従って、選択したシミュレータのudidを引数として渡して呼び出します。

  1. Xcodeスキームを編集します(ある場合はUIテストの特定のスキーム)
  2. 移動:テスト>事前アクション
  3. 「+」記号>「新しいスクリプト実行アクション」をタップして、新しいスクリプトを追加します。
  4. 重要:[ビルド設定の提供元]ドロップダウンで、UIテストターゲットではなく、メインのアプリターゲットを選択します。
  5. 次のスクリプトを下のテキスト領域に追加します。

Test> Pre-actions内のスクリプト:

#!/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. キーボード操作で任意のUIテストを実行します。守っシミュレータの再起動をし、ハードウェアキーボードが無効になっています。そして、テストのキーボード操作は正常に機能しています。:)

-1

Securetextfieldsでも同じ問題がありました。私のシミュレータのハードウェア接続オプションはそうでしたが、それでも問題が発生しました。最後に、これは私にとってはうまくいきました(Swift 3):

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

あなたのコードと質問で尋ねられたコードの違いは何ですか?
Shivam Pokhriyal
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.