可以测试IBAction吗?

sas*_*ash 6 ocunit ios xctest

对IBOutlets进行单元测试有点容易,但IBActions呢?我试图找到一种方法,但没有任何运气.有没有办法在View Controller中的IBAction和nib文件中的按钮之间进行单元测试连接?

Jon*_*eid 10

对于完整的单元测试,每个插座/操作需要三个测试:

  1. 插座是否挂在一起?
  2. 插座是否与我们想要的动作相关联?
  3. 直接调用操作,就像它已被插座触发一样.

我一直这样做TDD我的视图控制器.您可以在此截屏视频中看到一个示例.

听起来你在具体询问第二步.这是一个单元测试的例子,用于验证内部的修饰myButton将调用动作.doSomething:这是我如何使用OCHamcrest表达它.(sut是被测系统的测试夹具.)

- (void)testMyButtonAction {
    assertThat([sut.myButton actionsForTarget:sut
                              forControlEvent:UIControlEventTouchUpInside],
               contains(@"doSomething:", nil));
}
Run Code Online (Sandbox Code Playgroud)

或者,这是一个没有Hamcrest的版本:

- (void)testMyButtonAction {
    NSArray *actions = [sut.myButton actionsForTarget:sut
                              forControlEvent:UIControlEventTouchUpInside];
    XCTAssertTrue([actions containsObject:@"doSomething:"]);
}
Run Code Online (Sandbox Code Playgroud)


sas*_*ash 5

我是用OCMock做的,像这样:

MyViewController *mainView =  [[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil];
[mainView view];

id mock =  [OCMockObject partialMockForObject:mainView];

//testButtonPressed IBAction should be triggered
[[mock expect] testButtonPressed:[OCMArg any]];

//simulate button press 
[mainView.testButton sendActionsForControlEvents: UIControlEventTouchUpInside];

[mock verify];
Run Code Online (Sandbox Code Playgroud)

如果未连接IBAction,则测试将失败,并显示错误"未调用预期方法".


Jul*_*lon 5

这是我在Swift中使用的内容。我创建了一个可以在所有UIViewController单元测试中使用的辅助函数:

func checkActionForOutlet(outlet: UIButton?, actionName: String, event: UIControlEvents, controller: UIViewController)->Bool{
    if let unwrappedButton = outlet {
        if let actions: [String] = unwrappedButton.actionsForTarget(controller, forControlEvent: event)! as [String] {
            return(actions.contains(actionName))
        }
    }
    return false
}
Run Code Online (Sandbox Code Playgroud)

然后像这样从测试中调用它:

func testScheduleActionIsConnected() {
    XCTAssertTrue(checkActionForOutlet(controller.btnScheduleOrder, actionName: "scheduleOrder", event: UIControlEvents.TouchUpInside, controller: controller ))
}
Run Code Online (Sandbox Code Playgroud)

我基本上确保按钮btnScheduleOrder具有与事件TouchUpInside的名称scheduleOrder相关联的IBAction。我还需要传递包含按钮的控制器,以此来验证操作的目标。

您还可以通过添加其他else子句使它更加复杂,以防unwrappedButton不存在(这意味着插座不存在)。由于我想分开商店和行动测试,因此这里没有