XCTWaiter Ожидание не стреляет
Я использую XCTWaiter для ожидания определенных условий в настройке автоматизации пользовательского интерфейса. Это мой пользовательский метод 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 ответа
Нашел обходной путь. Этот метод успешно работает в данном конкретном случае, где приведенный выше код не работает. Он блокирует выполнение кода 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
}
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")
}
}