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!
It also has XCTestException's which let me write async tests. Also great!
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.
Is there a way to have setUp wait until my database is ready before it runs tests?
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) } } }
Here's what I would like:
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) } } } }
XCTest provides two approaches for testing asynchronous code. For Swift code that uses async and await for concurrency, you mark your test methods async or async throws to test asynchronously.
Use these blocks to tear down state and clean up resources after a specific test method. XCTest runs the teardown methods once after each test method completes, with tearDown() first, then tearDownWithError() , then tearDown() async throws . Use these methods to tear down state after each test method.
Prepare and Tear Down State for a Test Class XCTest runs setUp() once before the test class begins. If you need to clean up temporary files or capture any data that you want to analyze after the test class is complete, use the tearDown class method on XCTestCase .
It's common in JavaScript for code to run asynchronously. When you have code that runs asynchronously, Jest needs to know when the code it is testing has completed, before it can move on to another test.
Rather than using semaphores or blocking loops, you can use the same waitForExpectationsWithTimeout:handler:
function you use in your async test cases.
// Swift override func setUp() { super.setUp() let exp = expectation(description: "\(#function)\(#line)") // Issue an async request let data = getData() db.overwriteDatabase(data) { // do some stuff exp.fulfill() } // Wait for the async request to complete waitForExpectations(timeout: 40, handler: nil) } // Objective-C - (void)setUp { [super setUp]; NSString *description = [NSString stringWithFormat:@"%s%d", __FUNCTION__, __LINE__]; XCTestExpectation *exp = [self expectationWithDescription:description]; // Issue an async request NSData *data = [self getData]; [db overwriteDatabaseData: data block: ^(){ [exp fulfill]; }]; // Wait for the async request to complete [self waitForExpectationsWithTimeout:40 handler: nil]; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With