What we’ll cover What is a Unit Test and what is TDD Gotchas with Xcode and Testing What I used to do in obj-c and what I learned to do better in Swift real-world coding example of starting a Swift app with testing
Unit testing is a development process in which the smallest testable parts of an application, called units, are individually and independently scrutinized for proper operation. Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle: first the developer writes an (initially failing) automated test case that defines a desired improvement or new function, then produces the minimum amount of code to pass that test
Unit Testing with Xcode has changed a little in each version. You could get away with more things like forcing views to load (to test your viewDidLoad logic) Objective-C was less restrictive in things being a dynamic language. Apple originally had no interest (it seemed) in the Unit Testing/TDD world, and did not get involved until iOS 7
Most of your testing focus should be on ViewControllers in fact, your testing should start at the ViewController (one test class per each) and then refactoring will give you a model and service layer.
In most cases especially with networking, you’ll want to use a mock and/or stubbed replacement for the service. For CoreData you can test with a real stack but you need to clean the storage out after each run of the test suite, this is where the tearDown() method comes in handy.
TDD and unit testing in general don’t work with tightly-coupled architectures. in fact there will probably be little you can test if separation of concerns and responsibilities are not assigned properly This is the silver-lining of unit testing, you enforce better coding practices the more you can test your app.
Layout your requirements first. Then form those into failing tests. 1) Title in Navigation Bar (according to specs) should say “Magenic Mobile” 2) Navigation Bar color should be red
In Obj-C world you could just call loadView or directly call viewDidLoad Apple has specifically said now in documentation to not do either of those things in tests, instead just call the getter of the view. https://www.natashatherobot.com/ios-testing-view-controllers-swift/
First rule of TDD!? write the failing test before attempting to solve the problem. To make this pass we’ll have to change how we created the viewController in setup()
Not the best way to set the bar background color especially (as in most cases) the color is needed for the whole app. Step 1, fail it Step 2, pass it Step 3, refactor it
Now the hard part, how to deal with external dependencies There’s probably an infinite number of opinionated ways to do this. Make a mock, don’t use a mock, call a real service, etc. Mocks and Stubs have always worked for me in C# so I’ll stick with that.
First off, we know we’ll have a network call to get a list of mobile group members. The key is to know what format is coming back, XML or JSON Then build a mock and stubbed service to emulate the behavior Once it’s fully emulated you can verify everything about the data, how to display it, how to parse it, etc.
In this simple contrived example we’re really just making a stub, a mock is really about verifying behavior. If you want to add some mock behavior, you can add flags for each method called. the flag is the mock behavior, the return of canned values is the stubbed behavior
Hand-rolling your own mocks for the purpose of unit-testing is tedious and time consuming. Yes you can use some third-party mocking libraries, and if you only plan on using mocks for testing, I’d recommend that approach. But, I’d recommend doing the first approach with manually creating your mock classes that also stub out responses You get the added benefit of an offline service to test your app when the service is down