如何在运行测试之前让XCTest等待setUp中的异步调用? [英] How can I get XCTest to wait for async calls in setUp before tests are run?

查看:199
本文介绍了如何在运行测试之前让XCTest等待setUp中的异步调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用Xcode 6编写集成测试,以配合单元测试和功能测试. XCTest有一个setUp()方法,该方法在每次测试之前都会被调用.伟大的!

I'm writing integration tests in Xcode 6 to go alongside my unit and functional tests. XCTest has a setUp() method that gets called before every test. Great!

它也具有XCTestException,可以让我编写异步测试.也很棒!

It also has XCTestException's which let me write async tests. Also great!

但是,我想在每次测试之前将测试数据填充到测试数据库中,然后setUp才开始执行测试,然后再执行异步数据库调用.

However, I would like to populate my test database with test data before every test and setUp just starts executing tests before the async database call is done.

是否有一种方法可以让setUp等到数据库准备就绪后再运行测试?

Is there a way to have setUp wait until my database is ready before it runs tests?

这是我现在所做的一个例子.由于setUp在数据库完成填充之前返回,因此我必须在每个测试中重复很多测试代码:

Here's an example of what I have do now. Since setUp returns before the database is done populating I have to duplicate a lot of test code every test:

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中执行异步操作,则应使用信号量技术:

There are two techniques for running asynchronous tests. XCTestExpectation and semaphores. In the case of doing something asynchronous in setUp, you should use the semaphore technique:

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 = DispatchSemaphore(value: 0)

    db.overwriteDatabase(data) {

        // do some stuff

        semaphore.signal()
    }

    semaphore.wait()
}

请注意,为了起作用,该onDone块不能在主线程上运行(否则将导致死锁).

Note, for that to work, this onDone block cannot run on the main thread (or else you'll deadlock).

如果此onDone块在主队列上运行,则可以使用运行循环:

If this onDone block runs on the main queue, you can use run loops:

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 {
        RunLoop.current.run(mode: .default, before: Date.distantFuture)
    }
}

这是一个非常低效的模式,但是根据overwriteDatabase的实施方式,可能有必要

This is a very inefficient pattern, but depending upon how overwriteDatabase was implemented, it might be necessary

注意,仅当您知道onDone块在主线程上运行时才使用此模式(否则,您将必须对finished变量进行一些同步).

Note, only use this pattern if you know that onDone block runs on the main thread (otherwise you'll have to do some synchronization of finished variable).

这篇关于如何在运行测试之前让XCTest等待setUp中的异步调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆