xctest - 如何测试是不是在按下按钮时加载新视图
Posted
技术标签:
【中文标题】xctest - 如何测试是不是在按下按钮时加载新视图【英文标题】:xctest - how to test if a new view loads on a button pressxctest - 如何测试是否在按下按钮时加载新视图 【发布时间】:2013-12-09 02:50:55 【问题描述】:刚开始使用 xcode 5 和 xctest。如何测试按钮按下时是否加载视图。我以编程方式添加了在单击 rightBarButtonItem 时调用的方法
action:@selector(onSettingsButton)
在 onSettingsButton 中
-(void) onSettingsButton
SettingsViewController *svc = [[SettingsViewController alloc] init];
[self.navigationController pushViewController:svc animated:YES];
如何编写 xctest 以确保 SettingsViewController 调出设置视图?谢谢。
【问题讨论】:
【参考方案1】:您需要一个交互测试——即检查对象之间交互的测试。在这种情况下,您要测试在导航控制器上使用SettingsViewController
调用-pushViewController:animated:
。所以我们想将一个模拟对象放入self.navigationController
中,我们可以问:“你按预期调用了吗?”
我将假设该类的简单名称:MyView。
我手动执行此操作的方法是子类化并覆盖navigationController
。所以在我的测试代码中,我会做这样的事情:
@interface TestableMyView : MyView
@property (nonatomic, strong) id mockNavigationController;
@end
@implementation TestableMyView
- (UINavigationController *)navigationController
return mockNavigationController;
@end
现在,测试将创建一个 TestableMyView 并设置其 mockNavigationController
属性,而不是创建 MyView。
这个 mock 可以是任何东西,只要它响应 -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 或 Kiwi 的模拟。但我认为先手动开始会有所帮助,以便您理解这些概念。然后选择有帮助的工具。如果你知道如何手工完成,你永远不会说,“模拟框架 X 不能满足我的需要!我被卡住了!”
【讨论】:
谢谢乔恩。我希望从主控制器获取 navigationControl,获取按钮(navigationItem.rightBarButtonItem)并向其发送新闻消息。然后检查当前可见的控制器是settingsViewController。我不知道如何按下按钮。我可以在代码中找到它。我想重点是我不想检查按钮按下是否有效。我认为确实如此,我只想检查正确的控制器是否出现。那么我在控制器上使用 onSettingsButton 所做的还不够吗?感谢您的耐心等待! 不测试实际的按钮按下。相反,1) 测试按钮是否已连接,2) 其目标是onSettingsButton
,以及 3) 直接调用 onSettingsButton
。不需要更多,因为您不需要测试 Apple 的代码。 …您的测试取决于推送视图控制器的实际活动,这可能很慢。它甚至可能在测试完成之前不会生效,因为它是一个实际的 UI 更改。此外,您的测试将您与tipViewController
联系在一起。 …但即使它有效,我希望你看到依赖注入和模拟的一般方法。它会很好地为您服务。
你在[sut onSettingsButton]
里面做什么?
那么 mockNavigationController 是如何得到想要的输出的呢?
TestableMyView
覆盖普通的-navigationController
以返回模拟。【参考方案2】:
找到一种方法。也许还有其他人..
- (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获取当前视图,它是应用程序的根视图,并检查它是否是一个SettingsViewController。
【讨论】:
您好,我使用您的代码进行 swift 但我的导航控制器总是返回 nil,您能解释一下原因吗? Objective C 也会发生这种情况吗?以上是关于xctest - 如何测试是不是在按下按钮时加载新视图的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有静态文本的情况下在 XCTest 中快速测试 Webview 是不是加载