3

I have a UIViewController that contains each of UITextField, UIButton and UILabel. I put something in the UITextField, press a button and the string is now capitalized in the UILabel.

My question is: how do I set up the IBAction in Swift for unit tests? If there is no way to test the action in Swift, what else can I do to test this?

Lucas Huang
  • 3,998
  • 3
  • 20
  • 29
noobsmcgoobs
  • 2,716
  • 5
  • 32
  • 52

3 Answers3

1

In the unit-testing world, the most difficult work could be UI testing. So, what you can do is to check whatever is available to you from the API.

You can not toggle an action or event like you are a phone user. So, you have to programmatically toggle actions or events in order to test on that. You will also have to programmatically initialize the UI elements yourself.

IBAction is just nothing but an indicator to tell UIStoryboard that this is a connector method, you can ignore and treat it as a normal method.

Lucas Huang
  • 3,998
  • 3
  • 20
  • 29
  • treating as a normal method - forgot about that, thanks. – noobsmcgoobs May 05 '15 at 07:40
  • well there's a way to get around it by writing a function and calling that in the IBAction instead of just writing the function in the action. You can call that function in the test by sending it to the view or the viewController – noobsmcgoobs May 05 '15 at 08:20
0

Unit Tests are not designed to test visual interface. It's made to test your code.

For testing the interface, you can use Apple's UI Automation tool or other external tools.

David Ansermot
  • 6,052
  • 8
  • 47
  • 82
0

Personally I tried to do a mock for the class and send the following code:

controllerMock.btnNoResults.sendActionsForControlEvents(UIControlEvents.TouchUpInside)

The problem is that the call is not being made to the mock so the test is useless.

The same method executed in Objective-C with OCMock works perfectly so what I do is I mix swift tests and Objective-C tests.

In order to setup the Objective-C test to test swift source code I need to basically do the following:

  1. Add OCMock to my test project
  2. Create an Objective-C test. It will ask me for the bridging header as usual
  3. Import "OCMock.h"
  4. VERY IMPORTANT: Import the header to access the swift functions on my project. This header is normally "ProjectName_Tests-Swift.h"
  5. Use the following code:

    -(void) testSeeMoreInformationAction{
        id mock = [OCMockObject partialMockForObject:pController];
        [[mock expect]seeMoreInformation];
    
        [pController.btnSeeMoreDetails sendActionsForControlEvents:UIControlEventTouchUpInside];
    
        [mock verify];
    }
    

Like this my test works. Also the good thing of mixing Objective-C with Swift and adding OCMock is that you now can test many other things in an easier way. Please note that when you use OCMock and Swift it only works with iOS SDK functions, it will not work well with you swift functions.

Here is an example of another OCMock test very useful with AlertView:

- (void)testLoginShowsAlertViewWhenNoUserNameAndPassword{
    pController.txtUserName.text = @"";
    pController.txtPassword.text = @"";
    id mock = [OCMockObject partialMockForObject:pController];
    [[mock expect]presentViewController:OCMOCK_ANY animated:YES completion:nil];

    [pController loginAction];

    [mock verify];
}

Please feel free to contact me if you need further assistance with Unit Testing. I think is one of the most interesting parts of swift development.

Julio Bailon
  • 3,735
  • 2
  • 33
  • 34