/ios-unit-testing-patterns

Unit testing code snippets for various iOS development scenarios.

iOS Unit Testing Patterns

Description

Unit testing code snippets for various iOS development scenarios.

Language

Swift 4.x

Unit Testing Framework

XCTest.framework

Sample Unit Tests for ViewController Classes

Working with a ViewController composed of TableViews

  • View Controller is composed of TableView
  • Conforms to and implements UITableViewDataSource protocol methods.
  • Conforms to and implements UITableViewDelegate protocol methods.
  • TableView has expected reuse identifier
  • TableViewCells have expected properties (e.g. cell label)

Working with a ViewController composed of CollectionViews

  • Conforms to and implements UICollectionViewDatasource protocol methods.
  • Conforms to and implements UICollectionViewDelegate protocol methods.
  • Conforms to and implements UICollectionViewDelegateFlowLayout protocol methods.

Working with NavigationItems

  • Testing initialization and state of back button (navigationItem.backBarButtonItem).
  • Testing state of custom title view (navigationItem.titleView).
  • Testing target-action pattern for Right Bar Button (navigationItem.rightBarButtonItem).
  • Testing UIBarButtonItem can pop ViewController from navigation stack.
  • Testing UIRightBarButtonItem has correct custom UIImage when toggled

Working with a ViewController composed of UISearchBar

  • Testing initialization and state of search bar after view loads.
  • Conforms to SearchBarDelegate protocol methods.
  • Testing of auto-suggest behavior between SearchBar.text and UITableView items.
  • Testing pre-processing of Search Text when 'Search' button tapped on virtual/soft keyboard.

Working with Segues between ViewControllers

Working with a ViewController composed of Custom Views

  • Testing initialization and state of Custom View properties when view loads.

Working with a ViewController composed of MKMapView

  • Testing state of MKMapView after view loads.
  • Conforms to and implements MKMapViewDelegate protocol methods.
  • Testing MapView adds annotations to the map.
  • Testing MapView adds specific types of MKAnnotation.

Working with a ViewConroller that uses CoreLocation

  • Conforms to and implements CLLocationManager protocol methods.

Working with a ViewController composed of a UISegmentedControl

  • Testing initialization and state of UISegmentedControl after view loads.
  • Testing UISegmentedControl action method is invoked on change.

Working with a ViewController composed of a UIPickerView

  • Testing initialization and state of UIPickerView after view loads.
  • Conforms to and implements UIPickerViewDataSource protocol methods.
  • Conforms to and implements UIPickerViewDelegate protocol methods.

Working with a ViewController composed of a UIButton

  • Testing initialization and state of UIButton after view loads.
  • Testing target-action pattern of UIButton.

Working with a ViewController composed of a UILabel

  • Testing initialization and state of UILabel after view loads.
  • Testing label state after invoking the action methods of other controls.

Working with a ViewController that presents a UIAlertController

  • Using a mock ViewController to confirm launching UIAlertViewController
  • Testing the initialization and state of UIAlertController once presented.

Sample Unit Tests for Model Classes

Testing Model Class Initialization

Testing Model Class methods

Asynchronous Integration Test When Model performs work over the Network

Model adopts the MKAnnotation protocol

Model can Process the Response From Async Network Request

Confirming Model object instantiation of a NSManagedObject subclass

Confirming that a NSManagedObject subclass Category properly seeds CoreData

Set Up for Testing ViewController

  • When unit testing ViewController classes in storyboards, make sure to explicitly declare a 'Storyboard ID' property in the Identity Inspector for that ViewController.
  • Use the @testable attribute before declaring your test case class (see sample below).
  • In the sample below, substitue MyViewController with the name of your UIViewController you are testing.
    import XCTest
    @testable import YourAppTargetName

    class UnitTestsTests: XCTestCase {

        var viewControllerUnderTest: MyViewController!

        override func setUp() {
            super.setUp()

            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            self.viewControllerUnderTest = storyboard.instantiateViewController(withIdentifier: "MyViewController") as! MyViewController

            self.viewControllerUnderTest.loadView()
            self.viewControllerUnderTest.viewDidLoad()
        }

        override func tearDown() {
            // Put teardown code here. This method is called after the invocation of each test method in the class.
            super.tearDown()
        }

        func testStuff() {
           XCTAssertEqual(1, 1)
        }
    }

Add a Test Case file

Below are steps for adding a Test Case file for an individual class that you are testing.

  • Right-click your Tests folder in the Xcode Project Navigator
  • Choose New File
  • Choose Cocoa Touch Class
  • Use a naming convention - such as appending Test to your class name. For example, use MapViewControllerTest for testing MapViewController.
  • Choose the Subclass of XCTestCase
  • Confirm the Test target is selected
  • Choose Create

Connect