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 是不是加载

React - 登录提交按钮以呈现新页面

如何在按下“停止”按钮时捕获捆绑的GDB在clion中发出的信号?

颤振:如何在按下后退按钮时不退出应用程序

如何仅在按下按钮时更新位置

Android:如何在按下按钮时关闭一个活动并在按下另一个按钮时关闭整个后台堆栈? [复制]