如何在UI测试期间在Swift应用程序中隐藏键盘

问题描述 投票:18回答:8

我刚开始在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测试期间有没有其他方法可以隐藏键盘?

ios swift user-interface testing xcode-ui-testing
8个回答
19
投票

如果您已经设置了文本字段以在textField.resignFirstResponder()委托方法中重新签名FirstResponder(通过self.view.endEditing(true)textFieldShouldReturn()),那么

textField.typeText("\n")

会做的。


5
投票

根据Joe's blog的一个问题,我有一个问题,在模拟器上运行几次后,键盘无法使用这段代码隐藏:

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

所以,我改成了:(谢谢乔)

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

我在这里尝试做的是在点击隐藏按钮后检测键盘是否仍然打开,如果它已经打开,我键入一个“\ n”,在我的情况下也会关闭键盘。

这也很棘手,因为有时模拟器失去了键盘输入的焦点,这可能会使测试失败,但根据我的经验,失败率低于我采取的其他方法。

我希望这可以提供帮助。


4
投票

我总是使用它以编程方式隐藏Swift UITesting中的键盘:

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

4
投票
XCUIApplication().toolbars.buttons["Done"].tap()

3
投票

您的问题的答案不在于您的测试代码,而在于您的应用代码。如果用户无法使用屏幕上的软件键盘输入文本然后点击按钮,您应该让测试关闭键盘(用户必须按,以点击按钮)或使视图可滚动。


1
投票

在运行测试之前,请确保在模拟器中关闭键盘。

硬件 - >键盘 - >连接硬件键盘。

然后使用粘贴板输入文本

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

1
投票

使用Swift 4.2,您现在可以使用以下代码段完成此操作:

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

1
投票

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

0
投票

我更喜欢搜索可能可以点击或继续的多个元素,或者你想要调用的任何元素。并选择正确的。

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

关于这一点的好处是你可以提供多个可以点击的元素,它首先搜索键盘元素。

另一个好处是,如果您在真实设备上进行测试,默认情况下键盘会打开。那么为什么不按键盘按钮呢?

当有多个按钮执行相同的操作时,我只使用此帮助程序,有些可能是隐藏的等等。

© www.soinside.com 2019 - 2024. All rights reserved.