I've had some luck building a passing test that uses XCTestExpectation
to verify that specific ViewController
s get pushed onto a UINavigationController
from a button press. The code looks like this:
// MyTestCase.m
- (void)setUp {
[super setUp];
_sut = // instantiate the UINavigationController somehow
[_sut beginAppearanceTransition:YES animated:NO];
// You have to trigger the topViewController's lifecycle methods as well, because doing it for UINavigationController's doesn't automatically do it for the topViewController
[_sut.topViewController beginAppearanceTransition:YES animated:NO];
}
- (void)tearDown {
[_sut.topViewController endAppearanceTransition];
[_sut endAppearanceTransition];
[super tearDown];
}
- (void)testThatItDoesWhatIWant {
// When
[_sut.topViewController.button sendActionsForControlEvents:UIControlEventTouchUpInside];
// Then
XCTestExpectation *expectation = [self expectationWithDescription:@"should push email sign up view controller"];
// Yield, and UIKit a chance to perform the non-animated view controller push
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 0), dispatch_get_main_queue(), ^{
// Some arbitrary assertions with Expecta syntax
expect([_sut topViewController]).toNot.beKindOf([InitialTopViewControllerType class]);
// ...
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:0.01f handler:nil];
}
Don't let the zero delay fool you — this actually runs and works well and does pass.
The problem is that when I have put a few more of these tests in (say, testThatItDoesWhatIWant2
) the same test suite, the tests start failing non-deterministically — as if there's some timing issue or race condition.
I don't really understand why there are timing issues, because I thought that XCTestExpectation
blocks the main thread, and XCTest
runs everything serially. There should be no problems.
Aucun commentaire:
Enregistrer un commentaire