在XCode单元测试中测试导航

时间:2015-05-07 05:55:55

标签: ios objective-c xcode unit-testing

我正在尝试在单元测试中测试UIViewControllers导航,我能够进行后端测试但是增加了测试UIViewControllers的测试的覆盖范围,

面对一个奇怪的问题所以我有一个ViewController(手动创建,没有Storyboard),它有两个按钮,点击这些按钮,你会看到另一个视图(在导航控制器上推新视图)。

viewDidLoad

中的初始化如下
// 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");

}

所以这个测试实际上失败的原因我想是因为我在调用带有动画的PushView控制器之后立即检查ViewController:是,如果我推动视图控制器没有动画测试传递(因为视图立即被推动并且断言检查确定)。

所以我的问题是,无论如何,我可以放一个钩子,在检查Assert之前检查View是否已被推送(我不想转动动画只是为了通过测试,因为它会杀死整个目的)我也不想放任何延迟。在运行测试逻辑之前,我可以以某种方式检查推送动画是否已完成并且视图最终位于顶部?

2 个答案:

答案 0 :(得分:2)

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];

答案 1 :(得分:1)

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