Unit Testing in Swift
or what I learned after getting it wrong a lot.
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
Unit testing is a development process in which the
smallest testable parts of an application, called units,
are individually and independently scrutinized for
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
Unit Testing with Xcode has changed a little in each
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
Apple originally had no interest (it seemed) in the Unit
Testing/TDD world, and did not get involved until iOS 7
New rules with Xcode 7 and Swift
If you get this error,
Start using @testable
In Objective-C we had OCUnit and OCMock
Had to pull in all kinds of headers when testing a
In Swift now you just pull in the module of
your app target
Every test class you make now comes with a
reminder to test performance.
Most of your testing focus should be on
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.
But how do you handle networking, Core Data, etc?
or at least not directly in the ViewControllers
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.
Lets create a quick viewController test
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
Lets instantiate the ViewController, then
make our first failing test case.
As we expected, it failed, in fact it should
always fail first if you’re doing Test-First
Still not passing…
Now comes the dilemma, what do I do to
force the view to load, layout, etc. ?
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
Next expectation was a navigation bar
hmm… no navbar to be found, or
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()
remember we have a Navigation Controller
starting off the workflow in the storyboard
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 just update your setup code again to
grab that appearance proxy usage
Doh! Now it’s failing again…
Now the hard part, how to deal with
There’s probably an infinite number of
opinionated ways to do this.
Make a mock, don’t use a mock, call a real
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.
The key to mocking and stubbing is to use
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
Add the protocol (not the MyService class)
as a property to your ViewController
Update your setup code to now inject this
It’s important that you do the dependency
injection before you call the view, because
Now verify with the mock (flagged)
behavior with a test
Now is a good time to use tearDown to
reset the flag
That was a mock test, how about a stub?
Yes, you can directly call the
UITableViewDelegate and datasource
methods in tests.
Now to make that test pass, code like you
normally would if the service responded
back with a set of strings.
Hand-rolling your own mocks for the
purpose of unit-testing is tedious and time
Yes you can use some third-party mocking
libraries, and if you only plan on using
mocks for testing, I’d recommend that
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