当使用并行测试同时运行所有测试时,输入文本字段是片断的。

问题描述 投票:1回答:1

我正在尝试使用 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)
}

我试过这些步骤,才变成这样。

  1. 只有 element.tap()element.typeText().
  2. 增加了守候存在(the assertExists() 块)
  3. 增加了 sleep() 等待几秒钟,键盘才会出现。
  4. 添加了 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)
}

所以我就这么做了:

  1. 只输入 element.tap()tap(pasteMenuItem, timeout: timeout, file: file, line: line) (这与 app.menuItems["Paste"].tap())
  2. 增加了 element.doubleTap()
  3. 增加了 element.press()

使用粘贴功能时,有时 "粘贴 "菜单项不显示,并出现此错误。failed - Element: "Paste" MenuItem does not exist!. 但有时却能正常工作。

所以,我现在是束手无策了。我如何在文本字段中输入一个文本,不管是运行所有测试还是运行单一的测试用例,在所有条件下都一定能工作?

先谢谢你了。

PS:在我的CI机上就能正常工作。这就奇怪了。

ios swift xcode xcode-ui-testing xcuitest
1个回答
0
投票

你可以试试这样的方法

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。我也把名字从 EasyPredicatePredicate

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
    }
© www.soinside.com 2019 - 2024. All rights reserved.