查看XCTWaiter()。wait(...)我相信我们可以等待多个期望使用此代码成为现实
let notHittablePredicate = NSPredicate(format: "hittable == false")
let myExpectation = XCTNSPredicateExpectation(predicate: notHittablePredicate, object: element)
let result = XCTWaiter().wait(for: [myExpectation], timeout: timeout)
//for takes array of expectations
但是这在所提供的期望中使用了AND。有没有办法在提供的期望中做OR。
就像我在登录时有一个用例,在点击提交后,我想等待两个元素中的一个。第一个元素是“您已经登录到另一台设备。如果您继续在其他设备上保存任何未保存的数据,将会丢失?”。第二个元素是登录后的主屏幕。所以任何人都可以出现。目前我首先等待第一个元素,直到超时,然后是第二个元素。但我希望在这里优化时间,并在两个元素中的任何一个存在时继续前进== true。然后我将检查element1是否存在,然后点击YES然后等待主屏幕,否则只断言element2的存在。
如果问题不明确,请发表评论。谢谢
答案 0 :(得分:3)
受http://masilotti.com/ui-testing-tdd/的启发,您不必依赖XCTWaiter
。您可以简单地运行一个循环并测试其中一个是否存在。
/// Waits for either of the two elements to exist (i.e. for scenarios where you might have
/// conditional UI logic and aren't sure which will show)
///
/// - Parameters:
/// - elementA: The first element to check for
/// - elementB: The second, or fallback, element to check for
/// - Returns: the element that existed
@discardableResult
func waitForEitherElementToExist(_ elementA: XCUIElement, _ elementB: XCUIElement) -> XCUIElement? {
let startTime = NSDate.timeIntervalSinceReferenceDate
while (!elementA.exists && !elementB.exists) { // while neither element exists
if (NSDate.timeIntervalSinceReferenceDate - startTime > 5.0) {
XCTFail("Timed out waiting for either element to exist.")
break
}
sleep(1)
}
if elementA.exists { return elementA }
if elementB.exists { return elementB }
return nil
}
然后你可以这样做:
let foundElement = waitForEitherElementToExist(elementA, elementB)
if foundElement == elementA {
// e.g. if it's a button, tap it
} else {
// element B was found
}
答案 1 :(得分:0)
Array
中的XCUIElement
而不是两个。
@discardableResult
func waitForAnyElement(_ elements: [XCUIElement], timeout: TimeInterval) -> XCUIElement? {
var returnValue: XCUIElement?
let startTime = Date()
while Date().timeIntervalSince(startTime) < timeout {
if let elementFound = elements.first(where: { $0.exists }) {
returnValue = elementFound
break
}
sleep(1)
}
return returnValue
}
可以像
一样使用let element1 = app.tabBars.buttons["Home"]
let element2 = app.buttons["Submit"]
let element3 = app.staticTexts["Greetings"]
foundElement = waitForAnyElement([element1, element2, element3], timeout: 5)
// do whatever checks you may want
if foundElement == element1 {
// code
}
答案 2 :(得分:0)
NSPredicate
也支持 OR 谓词。
例如,我写了这样的东西,以确保我的应用程序在我开始尝试在 UI 测试中与其交互之前完全完成启动。这是在检查应用中是否存在各种标志,我知道这些标志在启动后的每个可能的启动状态中都是独一无二的。
extension XCTestCase {
func waitForLaunchToFinish(app: XCUIApplication) {
let loginScreenPredicate = NSPredicate { _, _ in
app.logInButton.exists
}
let tabBarPredicate = NSPredicate { _, _ in
app.tabBar.exists
}
let helpButtonPredicate = NSPredicate { _, _ in
app.helpButton.exists
}
let predicate = NSCompoundPredicate(
orPredicateWithSubpredicates: [
loginScreenPredicate,
tabBarPredicate,
helpButtonPredicate,
]
)
let finishedLaunchingExpectation = expectation(for: predicate, evaluatedWith: nil, handler: nil)
wait(for: [finishedLaunchingExpectation], timeout: 30)
}
}
在测试运行时,在控制台中,有一系列重复检查我想要检查的各种按钮是否存在,每次检查之间的时间可变。
<块引用>t = 13.76s 等待 com.myapp.name 空闲
t = 18.15s 检查“我的标签栏”按钮是否存在
t = 18.88s 检查“帮助”按钮是否存在
t = 20.98s 检查“登录”按钮是否存在
t = 22.99s 检查“我的标签栏”按钮是否存在
t = 23.39s 检查“帮助”按钮是否存在
t = 26.05s 检查“登录”按钮是否存在
t = 32.51s 检查“我的标签栏”按钮是否存在
t = 16.49s 检查“登录”按钮是否存在
瞧,现在我可以同时进行,而不是单独等待每个元素。
这当然非常灵活,因为您可以根据需要添加任意数量的元素,无论您想要什么条件。如果您想要组合 OR 和 AND 谓词,您也可以使用 NSCompoundPredicate
来实现。这可以很容易地改编成一个更通用的函数,它接受像这样的元素数组:
func wait(for elements: XCUIElement...) { … }
甚至可以传递一个参数来控制它是使用 OR 还是 AND。
答案 3 :(得分:0)
嘿,其他对我们有用的替代方法。我也希望能帮助到其他人。
XCTAssert(
app.staticTexts["Hello Stack"]
.waitForExistence(timeout: 10) || app.staticTexts["Hi Stack"]
.waitForExistence(timeout: 10)
)