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.
- 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
- Storyboard has target Segue
- Testing a Segue is called using a Mock UIViewController
- Testing Segue passes data to Target ViewController
- Testing ViewController can respond to an Unwind Segue
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
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
- Twitter: @clintcabanero
- GitHub: ccabanero