xcode – 如何在运行测试之前如何让XCTest等待setUp中的异步调用
发布时间:2020-12-15 02:05:20 所属栏目:百科 来源:网络整理
导读:我在Xcode 6中编写集成测试,与我的单元和功能测试一起进行。 XCTest有一个setUp()方法,在每次测试之前被调用。大! 它还有XCTestException,它允许我写异步测试。也很棒! 但是,我想在每次测试之前使用测试数据填充测试数据库,而setUp只是在异步数据库调
我在Xcode 6中编写集成测试,与我的单元和功能测试一起进行。 XCTest有一个setUp()方法,在每次测试之前被调用。大!
它还有XCTestException,它允许我写异步测试。也很棒! 但是,我想在每次测试之前使用测试数据填充测试数据库,而setUp只是在异步数据库调用完成之前开始执行测试。 有没有办法让setUp等到我的数据库准备好运行测试之前呢? 这是我现在所做的一个例子。由于setUp在数据库完成填充之前返回,我必须每次测试复制很多测试代码: func test_checkSomethingExists() { let expectation = expectationWithDescription("") var expected:DatabaseItem // Fill out a database with data. var data = getData() overwriteDatabase(data,{ // Database populated. // Do test... in this pseudocode I just check something... db.retrieveDatabaseItem({ expected in XCTAssertNotNil(expected) expectation.fulfill() }) }) waitForExpectationsWithTimeout(5.0) { (error) in if error != nil { XCTFail(error.localizedDescription) } } } 这是我想要的: class MyTestCase: XCTestCase { override func setUp() { super.setUp() // Fill out a database with data. I can make this call do anything,here // it returns a block. var data = getData() db.overwriteDatabase(data,onDone: () -> () { // When database done,do something that causes setUp to end // and start running tests }) } func test_checkSomethingExists() { let expectation = expectationWithDescription("") var expected:DatabaseItem // Do test... in this pseudocode I just check something... db.retrieveDatabaseItem({ expected in XCTAssertNotNil(expected) expectation.fulfill() }) waitForExpectationsWithTimeout(5.0) { (error) in if error != nil { XCTFail(error.localizedDescription) } } } } 解决方法
有两种运行异步测试的方法。 XCTestExpectation和信号量。在setUp中执行异步操作的情况下,应该使用信号量技术:
override func setUp() { super.setUp() // Fill out a database with data. I can make this call do anything,here // it returns a block. let data = getData() let semaphore = dispatch_semaphore_create(0) db.overwriteDatabase(data) { // do some stuff dispatch_semaphore_signal(semaphore) } dispatch_semaphore_wait(semaphore,DISPATCH_TIME_FOREVER) } 注意,为了工作,这个onDone块不能在主线程上运行(否则你会死锁)。 如果此onDone块在主队列上运行,则可以使用运行循环: override func setUp() { super.setUp() var finished = false // Fill out a database with data. I can make this call do anything,here // it returns a block. let data = getData() db.overwriteDatabase(data) { // do some stuff finished = true } while !finished { NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode,beforeDate: NSDate.distantFuture()) } } 这是一个非常低效的模式,但是根据overwriteDatabase的实现方式,可能是必要的 注意,只有当你知道onDone块在主线程上运行时,才使用这种模式(否则你必须做一些完成变量的同步)。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |