iOS Unit Test Examples / Snippets

1 comment on iOS Unit Test Examples / Snippets

Written by

in

In this article I will post common iOS Unit testing examples for testing of:

  1. Asynchronous loading of data using REST API
  2. Loading of a UIView
  3. Method call after UITableViewCell is clicked
  4. Static UITableView sections have correct number of rows
  5. Loading of a UIView from UIStoryboard
  6. IBOutlet connection
  7. Model logic
  8. UITableViewCell subclass
  9. IBAction / Method is implemented
  10. Testing bundle name

Asynchronous loading of data using REST API

// Testing REST API GET /api/cities/ that returns an array of cities with id and name
- (void)testCitiesAPI
{
    // We create XCTestExpectation object to test asynchronous loading
    XCTestExpectation *testExpectation = [self expectationWithDescription:@"testCitiesAPI"];
    
    NSString *URLString = [NSString stringWithFormat:@"/api/cities/"];
    
    [[RSHTTPClient sharedClient] GET:URLString parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
        
        NSArray *jsonArray = (NSArray *)responseObject;
        
        // Checking that jsonArray is not empty
        XCTAssertNotNil(jsonArray);
        
        for (NSDictionary *dic in jsonArray) {
            RSCity *city = [RSCity objectWithProperties:dic];
            
            // Checking consistency of a model object created from JSON dic
            XCTAssertNotNil(city.name);
            XCTAssertNotEqual(city.sid, 0);
        }
        
        [testExpectation fulfill];
        
    } failure:^(NSURLSessionTask *task, NSError *error) {
        
        NSLog(@"Error: %@", error);
        XCTFail(@"Error in GET /api/cities/");
        
    }];
    
    // Waiting for 10 seconds untim fulfill is called when task is finished
    [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) {
        
    }];
}

Here [RSHTTPClient sharedClient] is an instance of AFHTTPSessionManager subclass. But it doesn’t matter, the main is the principle.

Loading of a UIView

@interface RSBaseViewControllerTests : XCTestCase

@property (nonatomic, strong) RSBaseViewController *vc;

@end

@implementation RSBaseViewControllerTests

- (void)setUp {
    [super setUp];
    
    self.vc = [[RSBaseViewController alloc] init];
    [self.vc view];
}

- (void)tearDown {
    self.vc = nil;
    [super tearDown];
}

- (void)testThatViewLoads {
    XCTAssertNotNil(self.vc.view);
}

@end

Method call after UITableViewCell is clicked

#import "OCMock.h"

# Mock objects for Objective-C
pod 'OCMock', '~> 3.4'

- (void)testThatHomekitRestoreCalled
{
    id mock = [OCMockObject partialMockForObject:self.vc];
    
    [[mock expect] restoreHomeKitClicked];
    
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:CCSettingsSectionRestoreHomeKit];
    [self.vc tableView:self.vc.tableView didSelectRowAtIndexPath:indexPath];
    
    [mock verify];
}

Here we verify that method restoreHomeKitClicked is called when user selects a specific row in UITableView.

Static UITableView sections have correct number of rows

- (void)testThatSectionsHaveCorrentNumberOfRows
{
    XCTAssertEqual([self.vc tableView:self.vc.tableView numberOfRowsInSection:CCSettingsSectionUpdate], 1);
    XCTAssertEqual([self.vc tableView:self.vc.tableView numberOfRowsInSection:CCSettingsSectionGeneral], 2);
    XCTAssertEqual([self.vc tableView:self.vc.tableView numberOfRowsInSection:CCSettingsSectionAdditional], 3);
    XCTAssertEqual([self.vc tableView:self.vc.tableView numberOfRowsInSection:CCSettingsSectionRestoreHomeKit], 1);
}

Loading of a UIView from UIStoryboard

- (void)setUp
{
    [super setUp];
    
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    self.vc = [storyboard instantiateViewControllerWithIdentifier:@"RECameraListViewController"];
    [self.vc performSelectorOnMainThread:@selector(loadView) withObject:nil waitUntilDone:YES];
    [self.vc view];
}


- (void)tearDown
{
    self.vc = nil;
    [super tearDown];
}


#pragma mark - View loading tests

- (void)testThatViewLoads
{
    XCTAssertNotNil(self.vc.view, @"View not initiated properly");
}

IBOutlet connection

- (void)testOutlets {
    XCTAssertNotNil(self.vc.vkButton);
    XCTAssertNotNil(self.vc.fbButton);
    XCTAssertNotNil(self.vc.googleButton);
    XCTAssertNotNil(self.vc.agreementTextView);
}

Model logic

- (void)testBalanceArrayCount
{
    CSAccount *account = [CSAccount sharedAccount];
    NSArray *balanceArray = [account balanceArrayForNumberOfMonths:12];
    
    XCTAssertEqual([balanceArray count], 13);
}

Here we test that an array, that is formed inside our model has correct number of items. Model logic testing obviously can be different depending of logic itself.

UITableViewCell subclass

- (void)testThatServerCellHasCorrectOutlets
{
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    REServerCell *cell = (REServerCell *)[self.vc tableView:self.vc.tableView cellForRowAtIndexPath:indexPath];
    XCTAssertNotNil(cell.cloudServerLabel, @"Should connect cloudServerLabel IBOutlet.");
    XCTAssertNotNil(cell.controlCenterServerLabel, @"Should connect controlCenterServerLabel IBOutlet.");
}


- (void)testThatServerCellHasCorrectContents
{
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    REServerCell *cell = (REServerCell *)[self.vc tableView:self.vc.tableView cellForRowAtIndexPath:indexPath];
    
    REServerItem *item = self.vc.tableData[0];
    
    NSString *cloudServerURL = cell.cloudServerLabel.text;
    NSString *controlCenterServerURL = cell.controlCenterServerLabel.text;
    
    XCTAssertTrue([cloudServerURL isEqualToString:item.cloudServer]);
    XCTAssertTrue([controlCenterServerURL isEqualToString:item.controlCenterServer]);
}

IBAction / Method is implemented

- (void)testThatHelperHasCustomizeAppearanceMethod
{
    XCTAssertTrue([self.helper respondsToSelector:@selector(customizeAppearance)]);
}

Testing bundle name

- (void)testThatBundleNameIsCorrect
{
    NSString *correctBundleName = @"YourBundleName";
    NSDictionary *infoDic = [[NSBundle mainBundle] infoDictionary];
    NSString *bundleName = infoDic[@"CFBundleName"];
    XCTAssertTrue([bundleName isEqualToString:correctBundleName], @"Strings are not equal %@ %@", correctBundleName, bundleName);
}

The last is a rare case, but helps to prevent someone changing a bundle name of project accidentally.

Comments

One response to “iOS Unit Test Examples / Snippets”

  1. DK Avatar
    DK

    Good!

Leave a Reply

Your email address will not be published. Required fields are marked *