我刚开始在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测试期间有没有其他方法可以隐藏键盘?
如果您已经设置了文本字段以在textField.resignFirstResponder()
委托方法中重新签名FirstResponder(通过self.view.endEditing(true)
或textFieldShouldReturn()
),那么
textField.typeText("\n")
会做的。
根据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”,在我的情况下也会关闭键盘。
这也很棘手,因为有时模拟器失去了键盘输入的焦点,这可能会使测试失败,但根据我的经验,失败率低于我采取的其他方法。
我希望这可以提供帮助。
我总是使用它以编程方式隐藏Swift UITesting中的键盘:
XCUIApplication().keyboards.buttons["Hide keyboard"].tap()
XCUIApplication().toolbars.buttons["Done"].tap()
您的问题的答案不在于您的测试代码,而在于您的应用代码。如果用户无法使用屏幕上的软件键盘输入文本然后点击按钮,您应该让测试关闭键盘(用户必须按,以点击按钮)或使视图可滚动。
在运行测试之前,请确保在模拟器中关闭键盘。
硬件 - >键盘 - >连接硬件键盘。
然后使用粘贴板输入文本
textField.tap()
UIPasteboard.generalPasteboard().string = "Some text"
textField.doubleTap()
app.menuItems["paste"].tap()
使用Swift 4.2,您现在可以使用以下代码段完成此操作:
let app = XCUIApplication()
if app.keys.element(boundBy: 0).exists {
app.typeText("\n")
}
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()
}
}
}
我更喜欢搜索可能可以点击或继续的多个元素,或者你想要调用的任何元素。并选择正确的。
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()
关于这一点的好处是你可以提供多个可以点击的元素,它首先搜索键盘元素。
另一个好处是,如果您在真实设备上进行测试,默认情况下键盘会打开。那么为什么不按键盘按钮呢?
当有多个按钮执行相同的操作时,我只使用此帮助程序,有些可能是隐藏的等等。