在Xcode UItesting的testing案例中延迟/等待
我正在尝试使用Xcode 7 beta 2中提供的新UItesting编写一个testing用例。该应用程序有一个login屏幕,用于呼叫服务器进行login。 这是一个延迟,因为这是一个asynchronous操作。
在继续执行下一步之前,是否有办法在XCTestCase中引起延迟或等待机制?
没有适当的文档可用,我经历了类的头文件。 无法find与此相关的任何内容。
任何想法/build议?
在Xcode 7 Beta 4中引入了asynchronousUItesting。要等待文本为“Hello,world!”的标签。 出现你可以做到以下几点:
let app = XCUIApplication() app.launch() let label = app.staticTexts["Hello, world!"] let exists = NSPredicate(format: "exists == 1") expectationForPredicate(exists, evaluatedWithObject: label, handler: nil) waitForExpectationsWithTimeout(5, handler: nil)
有关UItesting的更多细节可以在我的博客上find。
另外,你可以睡觉:
sleep(10)
由于UITests在另一个进程中运行,所以这个工作。 我不知道这是多么可取,但是有效。
Xcode 9引入了XCTWaiter的新技巧
testing用例明确地等待
wait(for: [documentExpectation], timeout: 10)
服务员实例委托testing
XCTWaiter(delegate: self).wait(for: [documentExpectation], timeout: 10)
服务员类返回结果
let result = XCTWaiter.wait(for: [documentExpectation], timeout: 10) if result == .timedOut { //handle timeout }
================================================== ==========
在Xcode 9之前
目标C
- (void)waitForElementToAppear:(XCUIElement *)element withTimeout:(NSTimeInterval)timeout { NSUInteger line = __LINE__; NSString *file = [NSString stringWithUTF8String:__FILE__]; NSPredicate *existsPredicate = [NSPredicate predicateWithFormat:@"exists == true"]; [self expectationForPredicate:existsPredicate evaluatedWithObject:element handler:nil]; [self waitForExpectationsWithTimeout:timeout handler:^(NSError * _Nullable error) { if (error != nil) { NSString *message = [NSString stringWithFormat:@"Failed to find %@ after %f seconds",element,timeout]; [self recordFailureWithDescription:message inFile:file atLine:line expected:YES]; } }]; }
用法
XCUIElement *element = app.staticTexts["Name of your element"]; [self waitForElementToAppear:element withTimeout:5];
迅速
func waitForElementToAppear(element: XCUIElement, timeout: NSTimeInterval = 5, file: String = #file, line: UInt = #line) { let existsPredicate = NSPredicate(format: "exists == true") expectationForPredicate(existsPredicate, evaluatedWithObject: element, handler: nil) waitForExpectationsWithTimeout(timeout) { (error) -> Void in if (error != nil) { let message = "Failed to find \(element) after \(timeout) seconds." self.recordFailureWithDescription(message, inFile: file, atLine: line, expected: true) } } }
用法
let element = app.staticTexts["Name of your element"] self.waitForElementToAppear(element)
要么
let element = app.staticTexts["Name of your element"] self.waitForElementToAppear(element, timeout: 10)
资源
从Xcode 8.3开始,我们可以使用XCTWaiter
http://masilotti.com/xctest-waiting/
func waitForElementToAppear(_ element: XCUIElement) -> Bool { let predicate = NSPredicate(format: "exists == true") let expectation = expectation(for: predicate, evaluatedWith: element, handler: nil) let result = XCTWaiter().wait(for: [expectation], timeout: 5) return result == .completed }
另一个诀窍是写一个wait
function,信贷去约翰Sundell显示给我
extension XCTestCase { func wait(for duration: TimeInterval) { let waitExpectation = expectation(description: "Waiting") let when = DispatchTime.now() + duration DispatchQueue.main.asyncAfter(deadline: when) { waitExpectation.fulfill() } // We use a buffer here to avoid flakiness with Timer on CI waitForExpectations(timeout: duration + 0.5) } }
并使用它
func testOpenLink() { let delegate = UIApplication.shared.delegate as! AppDelegate let route = RouteMock() UIApplication.shared.open(linkUrl, options: [:], completionHandler: nil) wait(for: 1) XCTAssertNotNil(route.location) }
编辑:
实际上,在我看来,在Xcode 7b4中,UItesting现在有expectationForPredicate:evaluatedWithObject:handler:
原版的:
另一种方法是旋转运行循环一段时间。 真的只有在知道需要等待多less(估计)时间时才有用
Obj-C: [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow: <<time to wait in seconds>>]]
Swift: NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate(timeIntervalSinceNow: <<time to wait in seconds>>))
如果您需要testing一些条件以继续testing,这并不是非常有用。 要运行条件检查,请使用while
循环。
iOS 11 / Xcode 9引入了<yourElement>.waitForExistence(timeout: 5)
。 这是本网站所有自定义实现的绝佳替代品!
根据@ Ted的回答 ,我使用了这个扩展:
extension XCTestCase { // Based on https://stackoverflow.com/a/33855219 func waitFor<T>(object: T, timeout: TimeInterval = 5, file: String = #file, line: UInt = #line, expectationPredicate: @escaping (T) -> Bool) { let predicate = NSPredicate { obj, _ in expectationPredicate(obj as! T) } expectation(for: predicate, evaluatedWith: object, handler: nil) waitForExpectations(timeout: timeout) { error in if (error != nil) { let message = "Failed to fulful expectation block for \(object) after \(timeout) seconds." self.recordFailure(withDescription: message, inFile: file, atLine: line, expected: true) } } } }
你可以像这样使用它
let element = app.staticTexts["Name of your element"] waitFor(object: element) { $0.exists }
它也允许等待一个元素消失,或任何其他属性改变(通过使用适当的块)
waitFor(object: element) { !$0.exists } // Wait for it to disappear
以下代码只适用于Objective C
- (void)wait:(NSUInteger)interval { XCTestExpectation *expectation = [self expectationWithDescription:@"wait"]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(interval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [expectation fulfill]; }); [self waitForExpectationsWithTimeout:interval handler:nil]; }
只要打电话给这个function,如下所示。
[self wait: 10];
根据XCUIElement的API,存在可用于检查查询是否存在,因此在某些情况下,以下语法可能会有用!
let app = XCUIApplication() app.launch() let label = app.staticTexts["Hello, world!"] while !label.exists { sleep(1) }
如果你确信你的期望将会得到满足,那么你可以尝试运行这个。 应该注意的是,如果wait等待时间太长,应该使用来自@Joe Masilotti的post的waitForExpectationsWithTimeout(_,handler:_)
。
- iOS 9中的新警告
- Xcode 7 iOS 9 UITableViewCell分隔符插入问题
- 在iOS 9上NSURLSession / NSURLConnection HTTP加载失败
- iOS 9 UITableView分隔符插入(重要的左边距)
- 我如何添加NSAppTransportSecurity到我的info.plist文件?
- 资源无法加载,因为应用传输安全策略需要使用安全连接
- 如何使用联系人框架获取iOS 9中的所有联系人logging
- Xcode 7.2:在“存档”中:解决问题:找不到“Cordova / CDVViewController.h”文件。 虽然在构build应用程序时没有这样的问题
- 使用Objective C在iOS 9中将状态栏文本颜色更改为光照