2013-12-09 36 views
5

刚开始xcode 5和xctest。如何测试按钮按下时加载视图。我已经加入编程方法rightBarButtonItem点击xctest - 如何测试一个新的视图加载按钮按

action:@selector(onSettingsButton) 

和onSettingsButton

-(void) onSettingsButton{ 
    SettingsViewController *svc = [[SettingsViewController alloc] init]; 
    [self.navigationController pushViewController:svc animated:YES]; 
} 

时调用如何编写xctest确保SettingsViewController可以调出设置有何看法?谢谢。

回答

4

您需要一个交互测试 - 即检查对象之间交互的测试。在这种情况下,您需要测试在导航控制器上调用-pushViewController:animated:SettingsViewController。所以我们想把一个模拟对象放入self.navigationController,我们可以问:“你按预期打电话了吗?”

我将假设该类的一个简单名称:MyView。

我会这样做的方式是子类和覆盖navigationController。所以在我的测试代码,我会做这样的事情:

@interface TestableMyView : MyView 
@property (nonatomic, strong) id mockNavigationController; 
@end 

@implementation TestableMyView 

- (UINavigationController *)navigationController 
{ 
    return mockNavigationController; 
} 

@end 

现在,而不是创建一个MyView的,测试将创建一个TestableMyView并设置其属性mockNavigationController

这个模拟可以是任何事情,只要它响应-pushViewController:animated:并记录参数。下面是一个简单的例子,用手工:

@interface MockNavigationController : NSObject 
@property (nonatomic) int pushViewControllerCount; 
@property (nonatomic, strong) UIViewController *pushedViewController; 
@property (nonatomic) BOOL wasPushViewControllerAnimated; 
@end 

@implementation MockNavigationController 

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated 
{ 
    self.pushViewControllerCount += 1; 
    self.pushedViewController = viewController; 
    self.wasPushViewControllerAnimated = animated; 
} 

@end 

最后,这里有一个测试:

- (void)testOnSettingsButton_ShouldPushSettingsViewController 
{ 
    // given 
    MockNavigationController *mockNav = [[MockNavigationController alloc] init]; 
    TestableMyView *sut = [[TestableMyView alloc] init]; 
    sut.mockNavigationController = mockNav; 

    // when 
    [sut onSettingsButton]; 

    // then 
    XCTAssertEquals(1, mockNav.pushViewControllerCount); 
    XCTAssertTrue([mockNav.pushedViewController isKindOfClass:[SettingsViewController class]]); 
} 

这些东西可以通过使用模拟对象的框架,如OCMock,OCMockito,或猕猴桃的嘲笑被简化。但我认为这有助于先从手开始,以便理解这些概念。然后选择有帮助的工具。如果你知道如何手工完成,你永远不会说:“嘲笑框架X不能做我需要的东西!我被困住了!”

+0

谢谢乔恩。我希望从主控制器获取navigationControl,获取按钮(navigationItem.rightBarButtonItem)并向它发送一个新闻报道。然后检查当前可见的控制器是settingsViewController。我不知道如何按下按钮。我可以在代码中找到它。我想重点是我不想检查按钮按钮的作品。我假设它,我只是想检查正确的控制器出现。那么,我在控制器上使用onSettingsButton的程度还不够?感谢您的耐心等待 ! –

+1

不要测试实际的按钮按下。相反,1)测试按钮连接,2)它的目标是'onSettingsButton',并且3)直接调用'onSettingsButton'。不需要更多,因为您不需要测试Apple的代码。 ...您的测试取决于推送视图控制器的实际活动,这可能很慢。在测试结束之前甚至可能不会生效,因为这是一个实际的UI更改。另外你的测试将你绑定到'tipViewController'。 ......但即使它有效,我也希望你看到依赖注入和嘲弄的一般方法。它会为你服务。 –

+0

你在做什么'[sut onSettingsButton]'? –

1

找到了一种方法。也许有其他人..

- (void)testSettingsViewShowsWhenSettingsButtonIsClicked{ 
    [self.tipViewController onSettingsButton]; 
    id temp = self.tipViewController.navigationController.visibleViewController; 
    XCTAssertEqual([temp class], [SettingsViewController class], @"Current controller should be Settings view controller"); 
} 

首先调用onSettingsButton,这与点击按钮相同,但不是真的。也许这个简单的测试案例可以吗?如何模拟实际的新闻?

然后从tipviewcontoller获取当前视图,该视图是应用程序的rootview并检查它是否为SettingsViewController。

+0

嗨,我用你的代码为swift,但我的导航控制器总是返回零,你能解释为什么吗? Objective C也会发生这种情况吗? –