├── .gitignore └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | iOS Unit Testing Patterns 2 | ========================= 3 | 4 | ### Description 5 | 6 | Unit testing code snippets for various iOS development scenarios. 7 | 8 | ### Language 9 | 10 | Swift 4.x 11 | 12 | ### Unit Testing Framework 13 | 14 | XCTest.framework 15 | 16 | ### Sample Unit Tests for ViewController Classes 17 | 18 | __[Working with a ViewController composed of TableViews](https://gist.github.com/ccabanero/39ee6d5fd7b289dee695)__ 19 | 20 | * View Controller is composed of TableView 21 | * Conforms to and implements UITableViewDataSource protocol methods. 22 | * Conforms to and implements UITableViewDelegate protocol methods. 23 | * TableView has expected reuse identifier 24 | * TableViewCells have expected properties (e.g. cell label) 25 | 26 | __[Working with a ViewController composed of CollectionViews](https://gist.github.com/ccabanero/6ef47c1aeb21acfb326d30f6b01825d1)__ 27 | 28 | * Conforms to and implements UICollectionViewDatasource protocol methods. 29 | * Conforms to and implements UICollectionViewDelegate protocol methods. 30 | * Conforms to and implements UICollectionViewDelegateFlowLayout protocol methods. 31 | 32 | __[Working with NavigationItems](https://gist.github.com/ccabanero/4a1a4bfbf5fa3fbbb1070c8765c3de73)__ 33 | 34 | * Testing initialization and state of back button (navigationItem.backBarButtonItem). 35 | * Testing state of custom title view (navigationItem.titleView). 36 | * Testing target-action pattern for Right Bar Button (navigationItem.rightBarButtonItem). 37 | * Testing UIBarButtonItem can pop ViewController from navigation stack. 38 | * [Testing UIRightBarButtonItem has correct custom UIImage when toggled](https://gist.github.com/ccabanero/ed9111e472f6cb283ff8c3e714712efa) 39 | 40 | __[Working with a ViewController composed of UISearchBar](https://gist.github.com/ccabanero/0f20b0708c0d756327995e58ff3309d4)__ 41 | 42 | * Testing initialization and state of search bar after view loads. 43 | * Conforms to SearchBarDelegate protocol methods. 44 | * Testing of auto-suggest behavior between SearchBar.text and UITableView items. 45 | * Testing pre-processing of Search Text when 'Search' button tapped on virtual/soft keyboard. 46 | 47 | __Working with Segues between ViewControllers__ 48 | 49 | * [Storyboard has target Segue](https://gist.github.com/ccabanero/a0fbb675f44a5136d2811d21a77e332a) 50 | * [Testing a Segue is called using a Mock UIViewController](https://gist.github.com/ccabanero/9f7ad6775eacec3cc997) 51 | * [Testing Segue passes data to Target ViewController](https://gist.github.com/ccabanero/308db4882b7ca4967ebb5d17530177f3) 52 | * [Testing ViewController can respond to an Unwind Segue](https://gist.github.com/ccabanero/177a54d2be3694f08c4f3c8f02f74394) 53 | 54 | __[Working with a ViewController composed of Custom Views](https://gist.github.com/ccabanero/ac7237e4591092130326)__ 55 | 56 | * Testing initialization and state of Custom View properties when view loads. 57 | 58 | __[Working with a ViewController composed of MKMapView](https://gist.github.com/ccabanero/90c73c46ed1671298775)__ 59 | 60 | * Testing state of MKMapView after view loads. 61 | * Conforms to and implements MKMapViewDelegate protocol methods. 62 | * Testing MapView adds annotations to the map. 63 | * Testing MapView adds specific types of MKAnnotation. 64 | 65 | __[Working with a ViewConroller that uses CoreLocation](https://gist.github.com/ccabanero/dd35e7bee8205ad225f3de1391027aa5)__ 66 | 67 | * Conforms to and implements CLLocationManager protocol methods. 68 | 69 | __[Working with a ViewController composed of a UISegmentedControl](https://gist.github.com/ccabanero/e204496231a41759fa94)__ 70 | 71 | * Testing initialization and state of UISegmentedControl after view loads. 72 | * Testing UISegmentedControl action method is invoked on change. 73 | 74 | __[Working with a ViewController composed of a UIPickerView](https://gist.github.com/ccabanero/8d1dfa65218b8bb10ebf)__ 75 | 76 | * Testing initialization and state of UIPickerView after view loads. 77 | * Conforms to and implements UIPickerViewDataSource protocol methods. 78 | * Conforms to and implements UIPickerViewDelegate protocol methods. 79 | 80 | __[Working with a ViewController composed of a UIButton](https://gist.github.com/ccabanero/b92197516342c0147688)__ 81 | 82 | * Testing initialization and state of UIButton after view loads. 83 | * Testing target-action pattern of UIButton. 84 | 85 | __[Working with a ViewController composed of a UILabel](https://gist.github.com/ccabanero/68cd8ff461316930f707)__ 86 | 87 | * Testing initialization and state of UILabel after view loads. 88 | * Testing label state after invoking the action methods of other controls. 89 | 90 | 91 | __[Working with a ViewController that presents a UIAlertController](https://gist.github.com/ccabanero/b88a77caba37f8dd9fbf)__ 92 | 93 | * Using a mock ViewController to confirm launching UIAlertViewController 94 | * Testing the initialization and state of UIAlertController once presented. 95 | 96 | ### Sample Unit Tests for Model Classes 97 | 98 | [Testing Model Class Initialization](https://gist.github.com/ccabanero/90c6e2aadfd4efa6b059333edeb2b314) 99 | 100 | [Testing Model Class methods](https://gist.github.com/ccabanero/4221831a4c527c0453a8506628df34af) 101 | 102 | [Asynchronous Integration Test When Model performs work over the Network](https://gist.github.com/ccabanero/24a46c777bb29da95ba5) 103 | 104 | [Model adopts the MKAnnotation protocol](https://gist.github.com/ccabanero/f6f8aeb7ea06073753bf) 105 | 106 | [Model can Process the Response From Async Network Request](https://gist.github.com/ccabanero/1160dc6d95182593d111) 107 | 108 | [Confirming Model object instantiation of a NSManagedObject subclass](https://gist.github.com/ccabanero/93501b0cc78e2023f119) 109 | 110 | [Confirming that a NSManagedObject subclass Category properly seeds CoreData](https://gist.github.com/ccabanero/3de1a0cfecc7cb4fa9e6) 111 | 112 | ### Set Up for Testing ViewController 113 | 114 | * When unit testing ViewController classes in storyboards, make sure to explicitly declare a 'Storyboard ID' property in the Identity Inspector for that ViewController. 115 | * Use the __@testable__ attribute before declaring your test case class (see sample below). 116 | * In the sample below, substitue __MyViewController__ with the name of your UIViewController you are testing. 117 | 118 | ```` 119 | import XCTest 120 | @testable import YourAppTargetName 121 | 122 | class UnitTestsTests: XCTestCase { 123 | 124 | var viewControllerUnderTest: MyViewController! 125 | 126 | override func setUp() { 127 | super.setUp() 128 | 129 | let storyboard = UIStoryboard(name: "Main", bundle: nil) 130 | self.viewControllerUnderTest = storyboard.instantiateViewController(withIdentifier: "MyViewController") as! MyViewController 131 | 132 | self.viewControllerUnderTest.loadView() 133 | self.viewControllerUnderTest.viewDidLoad() 134 | } 135 | 136 | override func tearDown() { 137 | // Put teardown code here. This method is called after the invocation of each test method in the class. 138 | super.tearDown() 139 | } 140 | 141 | func testStuff() { 142 | XCTAssertEqual(1, 1) 143 | } 144 | } 145 | ```` 146 | 147 | ### Add a Test Case file 148 | 149 | Below are steps for adding a Test Case file for an individual class that you are testing. 150 | 151 | * Right-click your Tests folder in the Xcode Project Navigator 152 | * Choose New File 153 | * Choose Cocoa Touch Class 154 | * Use a naming convention - such as appending Test to your class name. For example, use MapViewControllerTest for testing MapViewController. 155 | * Choose the Subclass of __XCTestCase__ 156 | * Confirm the Test target is selected 157 | * Choose Create 158 | 159 | ### Connect 160 | 161 | * Twitter: [@clintcabanero](http://twitter.com/clintcabanero) 162 | * GitHub: [ccabanero](http:///github.com/ccabanero) 163 | 164 | 165 | 166 | --------------------------------------------------------------------------------