我正在尝试使用 XCUITest
. 目前,我在将一个文本输入到一个 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!
. 但有时却能正常工作。
所以,我现在是束手无策了。我如何在文本字段中输入一个文本,不管是运行所有测试还是运行单一的测试用例,在所有条件下都一定能工作?
先谢谢你了。
PS:在我的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.comZhipingYangEinsteinblob600854f9b6f93bb3694deddb3fb6edbae0f67f74ClassUITestModelEasyPredicate.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
}