XCTWaiter期望未被解雇

时间:2017-10-23 02:03:18

标签: swift xcode automated-tests xcuitest

我正在使用XCTWaiter等待UI自动化设置中的某些条件。这是我的自定义waitFor方法:

// UITools.swift
public class func waitFor(_ element:Any, timeout:UInt, clause:String) -> Bool
{
    let predicate = NSPredicate(format: clause)
    let expectation = testcase.expectation(for: predicate, evaluatedWith: element)

    print("Waiting for \(element) to become \"\(clause)\" within \(timeout) seconds ...")

    let result = XCTWaiter.wait(for: [expectation], timeout: TimeInterval(timeout))

    switch result
    {
        case .completed:
            return true
        case .invertedFulfillment:
            print("waitFor result is in inverted fulfillment.")
            return true
        case .timedOut:
            print("waitFor result is timed out.")
        case .incorrectOrder:
            print("waitFor result is in incorrect order.")
        case .interrupted:
            print("waitFor result is interrupted.")
    }

    return false
}

这种方法在我等待XCUIElements的情况下工作正常但我有一种情况我想等待网络请求完成所以我使用一个标志,一旦网络请求完成就设置为true。这是一个简化的例子:

class Hub : NSObject
{
    var isTestRailCasesRetrived = false

    func retrieveTestRailCaseData()
    {
        isTestRailCasesRetrived = false

        testrailClient.getTestCases()
        {
            (response:TestRailModel) in
                // Do processing here ...
                print("Found \(totalCases) TestRail cases for suite with ID \(suite.id).")
                self.isTestRailCasesRetrived = true
        }

        UITools.waitFor(self, timeout: 30, clause: "isTestRailCasesRetrived == true")
    }
}

然而,XCTWaiter在超时后永远不会达到完全且刚刚超时。在这种情况下似乎永远不会评估isTestRailCasesRetrived。有人知道为什么吗?

2 个答案:

答案 0 :(得分:0)

找到了解决方法。这种方法在上述代码没有的特殊情况下成功运行。它阻止XCUITest代码执行,直到这个等待循环结束......

/// Ass-simple brute force wait method for when nothing else works.
///
public class func waitUntil(timeout:Int = 30, evalblock:@escaping (() -> Bool))
{
    var count = 0
    repeat
    {
        if count >= timeout || evalblock() == true
        {
            break
        }
        else
        {
            Darwin.sleep(1)
        }
        count += 1
    }
    while true
}

答案 1 :(得分:0)

NSPredicate 与 Objective-C 运行时一起使用,并且由它评估的属性或函数必须用 @objc 属性标记。

解决方案:

class Hub : NSObject
{
    @objc var isTestRailCasesRetrived = false

    func retrieveTestRailCaseData()
    {
        isTestRailCasesRetrived = false

        testrailClient.getTestCases()
        {
            (response:TestRailModel) in
                // Do processing here ...
                print("Found \(totalCases) TestRail cases for suite with ID \(suite.id).")
                self.isTestRailCasesRetrived = true
        }

        UITools.waitFor(self, timeout: 30, clause: "isTestRailCasesRetrived == true")
    }
}