web-dev-qa-db-ja.com

UIテスト中にSwiftアプリでキーボードを非表示にする方法

私はXcode 7でのUIテストから始めて、この問題にぶつかりました:

テキストフィールドにテキストを入力してからボタンをクリックする必要があります。残念ながら、このボタンは、テキストフィールドにテキストを入力しているときに表示されたキーボードの後ろに隠れています。 Xcodeはスクロールして表示できるようにしていますが、ビューがスクロールできないため失敗します。

私の現在の解決策はこれです:

let textField = app.textFields["placeholder"]
textField.tap()
textField.typeText("my text")
app.childrenMatchingType(.Window).elementBoundByIndex(0).tap() // hide keyboard
app.buttons["hidden button"].tap()

私のViewControllerがタッチをインターセプトしているので、これを行うことができます:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    view.endEditing(false)
    super.touchesBegan(touches, withEvent: event)
}

私のソリューションには本当に満足していませんが、UIテスト中にキーボードを非表示にする方法は他にありますか?

21
leizeQ

textField.resignFirstResponder()デリゲートメソッドでFirstResponderを辞任するようにテキストフィールドを設定した場合(self.view.endEditing(true)またはtextFieldShouldReturn()を介して)、次に

textField.typeText("\n")

それを行います。

21
bbjay
XCUIApplication().toolbars.buttons["Done"].tap()
5
reutsey

ジョーのブログ への質問に基づいて、シミュレーターで数回実行した後、キーボードがこのコードの一部を使用して非表示にできないという問題があります。

XCUIApplication().keyboard.buttons["Hide keyboard"]

だから、私はそれを次のように変更しました:(ありがとうJoe)

XCUIApplication().keyboard.buttons["Hide keyboard"]
let firstKey = XCUIApplication().keys.elementBoundByIndex(0)
if firstKey.exists {
   app.typeText("\n")
}

ここで私がしようとしているのは、非表示ボタンをタップした後もキーボードがまだ開いているかどうかを検出することです。ボタンが上にある場合は、「\ n」と入力すると、キーボードも閉じます。

シミュレーターがキーボードタイピングのフォーカスを失い、テストが失敗する可能性があるため、これもトリッキーです。しかし、私の経験では、失敗率は私が取った他のアプローチよりも低くなっています。

これがお役に立てば幸いです。

5
katu

Swift UITesting:

XCUIApplication().keyboards.buttons["Hide keyboard"].tap()
5

あなたの質問への答えは、テストコードではなくアプリコードにあります。ユーザーが画面上のソフトウェアキーボードを使用してテキストを入力してボタンをタップできない場合は、テストでキーボードを非表示にする(ユーザーがボタンをタップするために必要となる)か、ビューをスクロール可能にする必要があります。 。

3
Aaron Sofaer

Swift 5ヘルパー関数

func dismissKeyboardIfPresent()
{
    if app.keyboards.element(boundBy: 0).exists
    {
        if UIDevice.current.userInterfaceIdiom == .pad
        {
            app.keyboards.buttons["Hide keyboard"].tap()
        }
        else
        {
            app.toolbars.buttons["Done"].tap()
        }
    }
}
3
trishcode

Swift 4.2を使用すると、次のスニペットでこれを実現できます。

let app = XCUIApplication()
if app.keys.element(boundBy: 0).exists {
    app.typeText("\n")
}
1
CodeBender

テストを実行する前に、シミュレータでキーボードがオフになっていることを確認してください。

ハードウェア->キーボード->ハードウェアキーボードの接続。

次に、ペーストボードを使用してテキストを入力します

textField.tap()
UIPasteboard.generalPasteboard().string = "Some text"
textField.doubleTap()
app.menuItems["paste"].tap()
1
365SplendidSuns

タップしたり続行したりするために表示されている可能性がある複数の要素を検索することをお勧めします。そして、正しいものを選択してください。

class ElementTapHelper {

    ///Possible elements to search for.
    var elements:[XCUIElement] = []

    ///Possible keyboard element.
    var keyboardElement:XCUIElement?

    init(elements:[XCUIElement], keyboardElement:XCUIElement? = nil) {
        self.elements = elements
        self.keyboardElement = keyboardElement
    }

    func tap() {
        let keyboard = XCUIApplication().keyboards.firstMatch
        if let key = keyboardElement, keyboard.exists  {
            let frame = keyboard.frame
            if frame != CGRect.zero {
                key.forceTap()
                return
            }
        }
        for el in elements {
            if el.exists && el.isHittable {
                el.forceTap()
                return
            }
        }
    }

}

extension XCUIElement {
    ///If the element isn't hittable, try and use coordinate instead.
    func forceTap() {
        if self.isHittable {
            self.tap()
            return
        }
        //if element isn't reporting hittable, grab it's coordinate and tap it.
        coordinate(withNormalizedOffset: CGVector(dx:0, dy:0)).tap()
    }
}

それは私にはうまくいきます。これは私が通常それを使用する方法です:

let next1 = XCUIApplication().buttons["Next"]
let keyboardNext = XCUIApplication().keyboards.firstMatch.buttons["Next"]
ElementTapHelper(elements: [next1], keyboardElement: keyboardNext).tap()

これの良い点は、タップできる複数の要素を提供でき、最初にキーボード要素を検索することです。

これのもう1つの利点は、実際のデバイスでテストする場合、デフォルトでキーボードが開くことです。では、キーボードボタンを押すだけではどうでしょうか。

このヘルパーは、同じことを行うボタンが複数あり、一部が非表示になっている場合にのみ使用します。

0
gngrwzrd