Reputation: 6971
In async tests is common, at least for me, to have to know the fulfilment count of an expectation to know how to assert.
For instance, a test to check this scenario:
func testOne() {
let expectData = expectation(description: "data")
expectData.expectedFulfillmentCount = 2
var expectDataFulfillmentCount = 0
sut.data = {
expectData.fulfill()
expectDataFulfillmentCount += 1
if expectDataFulfillmentCount == 1 {
XCTAssertEqual(sut.numberOfItems, 3)
sut.fetchNextPage()
} else if expectDataFulfillmentCount == 2 {
XCTAssertEqual(sut.numberOfItems, 6)
}
}
sut.fetch()
waitForExpectations(timeout: 0.1, handler: nil)
}
I am not happy with this pattern. I know I can slightly change how I assert when having expectations, this way:
func testTwo() {
let expectFirstData = expectation(description: "firstData")
let expectSecondData = expectation(description: "secondData")
sut.data = {
if sut.numberOfItems == 3 {
expectFirstData.fulfill()
sut.fetchNextPage()
} else if sut.numberOfItems == 6 {
expectSecondData.fulfill()
}
}
sut.fetch()
wait(for: [expectFirstData, expectSecondData], timeout: 0.1, enforceOrder: true)
}
But I don't like this neither because then I am not asserting (there is no XCTAssert
), I am just fulfilling expectations and then loosing the capacity to easily identify why and where the test failed. This pattern, though, is perfect for expectations over boolean values, like this one:
func testThree() {
let truePerformingOperationExpect = expectation(description: "truePerformingOperationExpect")
let falsePerformingOperationExpect = expectation(description: "falsePerformingOperationExpect")
sut.performingOperation = { fetching in
if fetching {
truePerformingOperationExpect.fulfill()
} else {
falsePerformingOperationExpect.fulfill()
}
}
sut.fetch()
wait(for: [truePerformingOperationExpect, falsePerformingOperationExpect], timeout: 0.1, enforceOrder: true)
}
For me, this could be easily solved if I can get the current fulfilment count of an expectation, it would clean up the test a lot and I would have both of best worlds. Is it possible? Is there any other way of doing this?
Upvotes: 5
Views: 2660
Reputation: 881
I ended up subclassing XCTestExpectation
:
class CountedFulfillmentTestExpectation: XCTestExpectation {
private(set) var currentFulfillmentCount: Int = 0
override func fulfill() {
currentFulfillmentCount += 1
super.fulfill()
}
}
Upvotes: 6