我正在尝试使用XCUITest
进行UI测试。目前,我在向UITextField
中输入文本时遇到了一些问题。以下是我在Robot
类中使用键盘键入文本的内容:
func typeTextToTextField(_ element: XCUIElement, text: String, timeout: TimeInterval = timeInterval,
file: StaticString, line: UInt) {
guard assertExists(element, timeout: timeout, file: file, line: line),
element.isHittable else {
return
}
element.tap()
sleep(2)
app.activate()
element.typeText("(text)n")
sleep(2)
}
在它变成这样之前,我已经尝试过这些步骤:
- 只有
element.tap()
和element.typeText()
- 添加了等待存在的保护(
assertExists()
块( - 添加了
sleep()
以等待几秒钟键盘出现 - 添加了
app.activate()
,因为显然有时进行查询会花费太长时间。关于这个错误的答案是,我应该先调用app.activate((
如果我用并行测试同时运行所有测试,那么使用它的一些测试会工作,但有些会失败。有些将正确显示键盘并正确键入文本,而另一些将无法显示键盘并显示此错误Failed to synthesize event: Neither element nor any descendant has keyboard focus.
。但当我一次运行一个测试时,它们都会是绿色的,并且工作得很完美。
所以,接下来,我尝试通过粘贴文本而不是键入文本来改变输入方式。这也不起作用。这是代码:
func pasteToTextField(_ element: XCUIElement, text: String, timeout: TimeInterval = timeInterval,
file: StaticString, line: UInt) {
app.activate()
guard assertExists(element, timeout: timeout, file: file, line: line),
element.isHittable else {
return
}
UIPasteboard.general.string = text
app.activate()
element.tap()
element.doubleTap()
element.press(forDuration: 1.2)
tap(pasteMenuItem, timeout: timeout, file: file, line: line)
sleep(5)
}
所以我做了:
- 只有
element.tap()
和tap(pasteMenuItem, timeout: timeout, file: file, line: line)
(与app.menuItems["Paste"].tap()
相同( - 添加
element.doubleTap()
- 添加
element.press()
使用粘贴功能时,有时粘贴菜单项不会显示,并出现以下错误:failed - Element: "Paste" MenuItem does not exist!
。但有时效果很好。
所以,我现在无计可施了。如何将文本输入到一个文本字段中,无论是运行所有测试还是运行单个测试用例,该字段都能在所有条件下工作?
提前谢谢。
附言:它在我的CI机器上运行得很好。这很奇怪。
您可以尝试类似的
extension XCUIElement {
func clearAndEnterText(_ text: String, app: XCUIApplication) {
let currentClipboard = UIPasteboard.general.string ?? ""
waitForElementToBecomeHittable(timeout: .small)
guard let stringValue = value as? String else {
return XCTFail("Tried to clear and enter text into a non string value")
}
if stringValue == text {
return
}
if stringValue.isNotEmpty {
if app.isKeyboardKeysAvaliable(key: XCUIKeyboardKey.delete.rawValue) {
let deleteString = stringValue.map { _ in XCUIKeyboardKey.delete.rawValue }.joined()
typeText(deleteString)
} else {
let selectAllButton = app.menuItems.element(predicate: .label(Comparison.containsAny, "Select All")).firstMatch
if !selectAllButton.waitForExistence(timeout: .small) {
press(forDuration: 1.1)
}
if selectAllButton.waitForExistence(timeout: .small) {
selectAllButton.tapElement()
}
}
}
if value(forKey: "hasKeyboardFocus") as? Bool ?? false {
typeText(text)
} else {
UIPasteboard.general.string = text
let pasteButton = app.menuItems.element(predicate: .label(Comparison.containsAny, "Paste"))
if !pasteButton.waitForExistence(timeout: .small) {
tap()
press(forDuration: 2.1)
}
if pasteButton.waitForExistence(timeout: .small) {
pasteButton.tapElement()
}
}
// Dismiss tooltip if it is still displayed
if app.menuItems.element.waitForExistence(timeout: .small) {
app.tap()
}
waitForElementToBecomeHittable(timeout: .small)
UIPasteboard.general.string = currentClipboard
}
}
注意:您需要导入此文件https://github.com/ZhipingYang/Einstein/blob/600854f9b6f93bb3694deddb3fb6edbae0f67f74/Class/UITest/Model/EasyPredicate.swift,我还将名称从EasyPredicate
更改为Predicate
extension XCUIApplication {
func isKeyboardKeysAvaliable(key: String) -> Bool {
let keyboard = keyboards.element(boundBy: 0)
if key.contains(all: "next") {
return keyboard.buttons[key].exists
} else {
return keyboard.keys[key].exists
}
}
}
extension XCUIElement {
@discardableResult
func waitForElementToBecomeHittable(timeout: Timeout) -> Bool {
return waitForExistence(timeout: timeout) && isHittable
}