在Xcode单元测试中测试导航

3

我正在尝试在单元测试中测试UIViewControllers导航,我已经能够进行后端测试,但为了增加测试覆盖率,想要测试UIViewControllers,

遇到了一个奇怪的问题,我有一个ViewController(手动创建,没有Storyboard),它有两个按钮,点击每个按钮会带你到另一个视图(将新视图推到导航控制器上)。

初始化如下所示:

// Setup the action of button
[self.button1 addTarget:self
                 action:@selector(goToView1)
       forControlEvents:UIControlEventTouchUpInside];

 [self.button2 addTarget:self
                  action:@selector(goToView2)
        forControlEvents:UIControlEventTouchUpInside];

这是我用于推送这两个视图的代码。
- (void)goToView1 
{
    // Go to the FAQ Screen
    ViewController1 *viewController = [[ViewController1 alloc] init];
    [self.navigationController pushViewController:viewController     
                                         animated:YES];
}
- (void)goToView2
{
      // Go to the checkin screen
      ViewController2 *viewController =[[ViewController2 alloc] init];
      [self.navigationController pushViewController:viewController
                                           animated:YES];
}

在我的测试类中,我正在尝试这样进行测试

- (void)testNavigation 
{
    //Initialize the view controller and call the navigation functions
    [self.testController goToView1];

    XCTAssertTrue([self.navigationController.topViewController 
                        isKindOfClass:[ViewController1 class]], 
                        @"Did not navigate Controller 1");

    [self.navigationController popToViewController:self.testController 
                                          animated:NO];

    [self.testController goToView2];

    XCTAssertTrue([self.navigationController.topViewController 
                  isKindOfClass:[ViewController2 class]], 
                  @"Did not navigate to Controller 2");

}

因此,我猜测这个测试实际上失败的原因是因为在使用animated:YES调用PushViewcontroller后立即检查ViewController。如果我不带动画地推送视图控制器,测试就会通过(因为视图立即被推送,断言检查正确)。那么我的问题是,有没有办法在检查断言之前放置钩子以检查视图是否已经被推送(我不想关闭动画,只是为了通过测试而杀死整个目的),也不想加任何随意的延迟。我可以以某种方式检查推动动画是否已完成并且视图最终位于顶部,然后运行测试逻辑吗?
2个回答

3

M David部分正确:你应该按照以下方式使用XCTestExpectation(与Xcode 6及以上版本一起使用)包装“dispatch_after”:

XCTestExpectation *completionExpectation = [self expectationWithDescription:@"WaitingForWhatever"];
double delayInSeconds = 3.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, popTime * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
       XCTAssertTrue([TestClass.navigationController.topViewController isKindOfClass:[requiredClass class]],@"View Controller not pushed properly");
       [completionExpectation fulfill];
});
[self waitForExpectationsWithTimeout: delayInSeconds+2 handler:nil];

0
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{

       XCTAssertTrue([TestClass.navigationController.topViewController isKindOfClass:[requiredClass class]],@"View Controller not pushed properly");
    });

我相信这对你来说应该有效,因为这个代码块在延迟1秒后执行。所以在此期间,你的视图控制器将被准确地推送,并且navigationConrtoller.TopViewController会更新为新推送的视图控制器。另外一点是,如果你正在使用测试类,那么self.navigationController不是正确的选择,它必须是yourCustomeObject.Navigationcontroller


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接